saving file as .pdf as recieved in http response error - java

For my project i need to download a pdf file from google drive using java
I get my httpresponse code 200 and by using following method i store it in abc.pdf file
String url = "https://docs.google.com/uc?id="+fileid+"&export=download";
URL obj = new URL(url);
HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
// optional default is GET
conn.setRequestMethod("GET");
//add request header
conn.setRequestProperty("User-Agent", USER_AGENT);
int responseCode = conn.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String inputLine;
OutputStream f0 = new FileOutputStream("C:\\Users\\Darshil\\Desktop\\abc.pdf",true);
while ((inputLine = in.readLine()) != null) {
//System.out.println(inputLine);
byte b[]=inputLine.getBytes();
//System.out.println(b);
f0.write(b);
}
in.close();
f0.close();
But when i try to open abc.pdf in my adobe reader x i get following error:
There was an error opening this document.The file is damaged and could not be repaired

You seem to be directly accessing the Google drive using Raw HTTP requests.
You may be better of using the Google Drive SDK. This link contains good examples to address the use cases you state in your question.
However if you do want to stick to your technique then you should not be using a BufferedReader.readLine(). This is because the PDF file is a binary finally that would depend upon the correct byte sequences to be preserved in order to be read correctly by the PDF reader software. Hopefully the below technique should help you:
//read in chunks of 2KB
byte[] buffer = new byte[2048];
int bytesRead = 0;
try(InputStream is = conn.getInputStream())
{
try(DataOutputStream os = new DataOutputStream(new FileOutputStream("file.pdf"))
{
while((bytesRead = is.read(buffer)) != -1)
{
os.write(buffer, 0, bytesRead);
}
}
}
catch(Exception ex)
{
//handle exception
}
Note that I am using the try-with-resources statement in Java 7
Hope this helps.

Related

File download from url using HttpURLConnection |HTTP 400 if file name contain space

I'm trying to download the files from url(soap request) using http connection, and below is my code, while executing i'm getting http = 400, because of file Name contain space (ac abc.pdf)
String downloadFileName = "ac abc.pdf";
String saveDir = "D:/download";
String baseUrl = "abc.com/AttachmentDownload?Filename=";
URL url = new URL(baseUrl + downloadFileName);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setReadTimeout(60 * 1000);
connection.setConnectTimeout(60 * 1000);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/octet-stream");
connection.setRequestProperty("SOAPAction", url.toString());
String userCredentials = "user:pass";
connection.setRequestProperty("Authorization", userCredentials);
connection.setDoInput(true);
connection.setDoOutput(true);
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
try (InputStream inputStream = connection.getInputStream()) {
String saveFilePath = saveDir + downloadFileName;
try (FileOutputStream outputStream = new FileOutputStream(saveFilePath)) {
int bytesRead = -1;
byte[] buffer = new byte[BUFFER_SIZE];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
}
while executing the above code getting the below output
responsecode400
response messageBad Request
No file to download. Server replied HTTP code: 400
let me know how can we format the url with the above situation
Spaces and some other symbols are not well tollerated in URL. You need to escape or encode them change your code
URL url = new URL(baseUrl + downloadFileName);
To:
URL url = new URL(baseUrl + URLEncoder.encode(downloadFileName, StandardCharsets.UTF_8.name());
That should resolve your problem. Besides there are Open Source libraries that resolve your issue for you. See Apache commons which is a popular solution. Another solution is MgntUtils library (version 1.5.0.2). It contains class HttpClient that allows you to do things very simple:
httpClient.sendHttpRequestForBinaryResponse(baseUrl + URLEncoder.encode(downloadFileName, StandardCharsets.UTF_8.name()", HttpClient.HttpMethod.POST);
This will return ByteBuffer that contains the response as raw bytes. The same class has method sendHttpRequest to get Textual response. Both methods throw IOException in case of failure. Here is the link to an article that explains where to get MgntUtils library as well as what utilities it has. In the article the HttpClient class is not mentioned (It is a new feature), but the library comes with well written javadoc. So look for javadoc for HttpClient class in that library.

getContentLength returning 1225, real length 3365

I am currently working with android and i am using a http connection with some headers (i havent included them or the real url for security purposes) to get a JSON response from an API, and feeding that response back into the application. The problem that i am having is that when using the getContentLength method of the http request, the wrong length is being returned (wrong length returned is 1225, the correct length in characters of the JSON array is 3365).
I have a feeling that the JSON is not fully loaded when my reader starts to read it, and as such is only reading the loaded JSON at that point. Is there any way around this, possibly using a delay on the HTTP connection or waiting until it is fully loaded to read the data?
URL url = new URL("https://www.exampleofurl.com");
HttpURLConnection request = (HttpURLConnection) url.openConnection();
request.connect();
int responseCode = request.getResponseCode();
if(responseCode == HttpURLConnection.HTTP_OK) {
InputStream inputStream = request.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream);
long contentLength2 = Long.parseLong(request.getHeaderField("Content-Length"));
Log.i("contentLength: ", "Content: " + contentLength2);
I generally don't recommend always relying on "Content-Length" as it may not be available (you get -1), or perhaps affected by intermediate proxy.
Why don't you just read your stream until it is exhausted into memory buffer (say, StringBuilder) and then get the actual size, for example :
BufferedReader br = new BufferedReader(inputStream); // inputStream in your code
String line;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line);
}
// finished reading
System.out.println("data size = " + sb.length());
JSONObject data = new JSONObject(sb.toString());
// and don't forget finally clauses with closing streams/connections

How to transfer a file from REST php server to a Java client

I've been surfing over this site looking for an example or "light at the end of the tunnel" about how to write a code that let me download a file from a REST server in PHP to a client in JAVA.
The client will make a GET request with an ID of the file, and then the PHP REST code should response with the file, and JAVA receive that file and store it in the Hard Drive.
Any idea...?
I tried to do the PHP Rest server like this...:
$file = 'path_to_file/file.mp3';
$content = readfile($file);
And this $content var, is sent as the response...
The client... I wrote is:
try {
URL url = new URL("url/to/rest/server");
HttpURLConnection conn (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "Content-Disposition: filename\"music.mp3\"");
if(conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code: " + conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
try {
String output;
File newFile = newFile("/some/path/file.mp3");
fileWriter fw = new FileWriter(newFile);
while ((output = br.readLine()) != null) {
fw.write(output);
}
fw.close();
} catch (IOException iox) {
//do
}
} catch (MalformedURLException e) {
//do
}
The problem with my examples is that when I receive the file on the client is kind of corrupted or something!... in my example with an mp3 file, any music player on the client says that file is corrupted or it doesn't work.
Thanks for any help.
When dealing with binary data (MP3 files) you should use InputStream and OutputStream and not Readers/Writers. Additionally, the BufferedReader.readLine() strips any 'newlines' from the output too.
Because you are using Readers/Writers, the binary data is being converted to Strings, and I am sure there's a lot of corruption happening.
Try the following:
InputStream is = conn.getInputStream();
byte[] buffer = new byte[10240]; // 10K is a 'reasonable' amount
try {
File newFile = newFile("/some/path/file.mp3");
FileOutputStream fos = new FileOutputStream(newFile);
int len = 0;
while ((len = is.read(buffer)) >= 0) {
fos.write(buffer, 0, len);
}
fos.close();
} catch (IOException iox) {
//do
}

Http Request for remote XML parsing

i'm stuck on this process from two days, before posting i've searched a lot of topic and looks like it's a so simple issue. But i didn't get the problem.
Scenario is basic: i want to parse an XML from a remote computer through http connection:
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
try {
URL url = new URL("http://host:port/file.xml");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept","application/xml");
InputStream is = connection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
PrintWriter pw = new PrintWriter("localfile_pw.xml");
FileOutputStream fos = new FileOutputStream("localfile_os.xml");
Then i tried three different ways to read the XML
Reading byte stream
byte[] buffer = new byte[4 * 1024];
int byteRead;
while((byteRead= is.read(buffer)) != -1){
fos.write(buffer, 0, byteRead);
}
Reading charachter per character
char c;
while((c = (char)br.read()) != -1){
pw.print(c);
System.out.print(c);
}
Reading line per line
String line = null;
while((line = br.readLine()) != null){
pw.println(line);
System.out.println(line);
}
In all cases my xml reading stops at the same point, after the same exact nuumber of bytes. And gets stuck without reading and without giving any exception.
Thanks in advance.
How about this (see IOUtils from Apache):
URL url = new URL("http://host:port/file.xml");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept","application/xml");
InputStream is = connection.getInputStream();
FileOutputStream fos = new FileOutputStream("localfile_os.xml");
IOUtils.copy(is, fos);
is.close();
fos.close();
The class supports persistent HTTP connections by default. If the size of the response is know at the time of the response, after it sends your data, the server will wait for another request. There are 2 ways of handling this:
Read the content-length:
InputStream is = connection.getInputStream();
String contLen = connection.getHeaderField("Content-length");
int numBytes = Integer.parse(contLen);
Read numBytes bytes from the input stream. Note: contLen may be null, in this case you should read until EOF.
Disable connection keep alive:
connection.setRequestProperty("Connection","close");
InputStream is = connection.getInputStream();
After sending the last byte of data the server will close the connection.

Incomplete content (buffer) of webpage

I want to read the content of a webpage with the following methods, but I only get 60-70 percent of it.
I've tried 2 different methods to read the webpage, both with the same result. I also tried different Urls. I get no errors or timeouts.
What I am doing wrong ?
URL url = new URL(uri.toString());
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try
{
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(in));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null)
{
sb.append(line + "\n");
}
br.close();
this.content = sb.toString();
}
finally
{
urlConnection.disconnect();
}
AND
HttpGet get = new HttpGet(uri);
HttpClient defaultHttp = new DefaultHttpClient(httpParameters);
HttpResponse response = defaultHttp.execute(get);
StatusLine status = response.getStatusLine();
if(status.getStatusCode() == HttpStatus.SC_OK)
{
HttpEntity entity = response.getEntity();
InputStream stream = entity.getContent();
String encoding = "utf-8";
//long length = entity.getContentLength();
//if(entity.getContentEncoding() != null)
//{
// encoding = entity.getContentEncoding().getValue();
//}
//if(length > 0)
//{
byte[] buffer = new byte[1024];
long read = 0;
do
{
read = stream.read(buffer);
if(read > 0)
{
this.content += new String(buffer, encoding);
}
}while(read > 0);
//}
}
#edit
I've tried it with C# and WinForms. I read the complete html source of that webpage.
With java-android it doesn't work.
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://www.kicker.de");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string content = reader.ReadToEnd();
reader.Close();
response.Close();
the httpurlconnection in apache's util jar has limited the biggest bytes in a response, i couldn't remember the number of it.
But in most of time ,may you use the http conncetion in UI thread , so sometimes it's not safe,and maybe will be killed, you can choose to deal with the http request in a thread but not the UI thread. So I want to know if you do it in the UT thread
I have currently the same Problem. I tried my Code in a simple Java Application and I receive the whole content. But on Android, the Content is incomplete. This Question is now a year old. I guess you have solved it in the meantime. Can you please add your Solution?
Edit:
I wrote the content into a File on my Android Device. The Content was complete!
It seems logcat doesn´t show the complete Output you receive from the Devie.

Categories

Resources