I am trying to download a PDF file with HttpClient, it is downloading the PDF file but pages are blank. I can see the bytes on console from response if I print them. But when I try to write it to file it is producing a blank file.
FileUtils.writeByteArrayToFile(new File(outputFilePath), bytes);
However the file is showing correct size of 103KB and 297KB as expected but its just blank!!
I tried with Output stream as well like:
FileOutputStream fileOutputStream = new FileOutputStream(outFile);
fileOutputStream.write(bytes);
Also tried to write with UTF-8 coding like:
Writer out = new BufferedWriter( new OutputStreamWriter(
new FileOutputStream(outFile), "UTF-8"));
String str = new String(bytes, StandardCharsets.UTF_8);
try {
out.write(str);
} finally {
out.close();
}
Nothing is working for me. Any suggestion is highly appreciated..
Update: I am using DefaultHttpClient.
HttpGet httpget = new HttpGet(targetURI);
HttpResponse response = null;
String htmlContents = null;
try {
httpget = new HttpGet(url);
response = httpclient.execute(httpget);
InputStreamReader dataStream=new InputStreamReader(response.getEntity().getContent());
byte[] bytes = IOUtils.toByteArray(dataStream);
...
You do
InputStreamReader dataStream=new InputStreamReader(response.getEntity().getContent());
byte[] bytes = IOUtils.toByteArray(dataStream);
As has already been mentioned in comments, using a Reader class can damage binary data, e.g. PDF files. Thus, you should not wrap your content in an InputStreamReader.
As your content can be used to construct an InputStreamReader, though, I assume response.getEntity().getContent() returns an InputStream. Such an InputStream usually can be directly used as IOUtils.toByteArray argument.
So:
InputStream dataStream=response.getEntity().getContent();
byte[] bytes = IOUtils.toByteArray(dataStream);
should already work for you!
Here is a method I use to download a PDF file from a specific URL. The method requires two string arguments, an url string (example: "https://www.ibm.com/support/knowledgecenter/SSWRCJ_4.1.0/com.ibm.safos.doc_4.1/Planning_and_Installation.pdf") and a destination folder path to download the PDF file (or whatever) into. If the destination path does not exist within the local file system then it is automatically created:
public boolean downloadFile(String urlString, String destinationFolderPath) {
boolean result = false; // will turn to true if download is successful
if (!destinationFolderPath.endsWith("/") && !destinationFolderPath.endsWith("\\")) {
destinationFolderPath+= "/";
}
// If the destination path does not exist then create it.
File foldersToMake = new File(destinationFolderPath);
if (!foldersToMake.exists()) {
foldersToMake.mkdirs();
}
try {
// Open Connection
URL url = new URL(urlString);
// Get just the file Name from URL
String fileName = new File(url.getPath()).getName();
// Try with Resources....
try (InputStream in = url.openStream(); FileOutputStream outStream =
new FileOutputStream(new File(destinationFolderPath + fileName))) {
// Read from resource and write to file...
int length = -1;
byte[] buffer = new byte[1024]; // buffer for portion of data from connection
while ((length = in.read(buffer)) > -1) {
outStream.write(buffer, 0, length);
}
}
// File Successfully Downloaded");
result = true;
}
catch (MalformedURLException ex) { ex.printStackTrace(); }
catch (IOException ex) { ex.printStackTrace(); }
return result;
}
Related
Getting the above error when trying to download large data using HttpGet
String uri = "";
getMethod = executeGet(uri);
httpClient.executeMethod(getMethod);
InputStream istream = getMethod.getResponseBodyAsStream();
byte[] data = IOUtils.toByteArray(istream);
FileUtils.writeByteArraytoFile(new File("xxx.zip"),data)
You are using a temporary byte array that might be the cause of the problem.
You can directly write the content of the stream to your file.
String uri = "";
getMethod = executeGet(uri);
httpClient.executeMethod(getMethod);
InputStream istream = getMethod.getResponseBodyAsStream();
IOUtils.copy(istream, new FileOutputStream(new File("xxx.zip"));
You're reading the entire response into the byte[] (memory). Instead, you could stream the output as you read it from istream with something like,
File f = new File("xxx.zip");
try (OutputStream os = new BufferedOutputStream(new FileOutputStream(f));) {
int c = -1;
while ((c = istream.read()) != -1) {
os.write(c);
}
} catch (Exception e) {
e.printStackTrace();
}
Right now I am working on a task to convert binary data in to a zip file
I am calling a url and getting a response from server like
A#B�ArE⏾�7�ϫ���f�걺N�����Yg���o_M^�D�T�U X_���e?� hi\ � �ڂ(� �0 rm��'�ed���� �:6h�k�ڗ� ���fnp���7��)��:��N�U�viR�,) II����M��Np�M��7��
n��
!A!) )AAFAq)Q)�y
y� ��.�����?���
��֞��ͅ��Ɲ_�O�����nc��f��w��ʰ�6��3 2�ƢZZ��N0� O{� mC� ��$��,>����������
���CW/)?�?٥��ߗ�d�=�R�J*E{2L���ח�W���ӑ_PRR�_#�_H��:������Ə�Ջ�J�^v�0wo��+�o���
�-Ä#�R6��P�(���0�WPj�k�
C�E
now I want to save this data to zip file i have searched a lot and find some links but not meet the goal.
here i have done
OutputStreamWriter osw = new OutputStreamWriter(openFileOutput(
"products.zip", Context.MODE_PRIVATE));
osw.write(data);
osw.close();
please guid me if you have any idea about this.
OutputStreamWriter osw
NO!
A Writer is made to write text, not binary.
In the first place, it looks like you read text as well, which you shouldn't.
Use an InputStream to read the original content, and an OutputStream to write into the file:
final OutputStream out = /* open your file using a FileOutputStream here */;
final byte[] buf = new byte[8096]; // size as appropriate
// "in" is the InputStream from the socket
int count;
try {
while ((count = in.read(buf)) != -1)
out.write(buf, 0, count);
out.flush();
} finally {
out.close();
}
Readers are not meant to read octet streams.
Reads text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines.
You're looking for a BufferedInputStream.
The getContent() method on the HttpEntity returns an InputStream. Wrap this around a BufferedInputStream and write it to a file or a ByteArrayOutputStream.
byte[] buffer = new byte[5 * 1024];
int numRead = -1;
while( (numRead = bufferedInputStream.read(buffer))!= -1)
{
byteArrayOutputStream.write(buffer, 0, numRead);
}
byteArrayOutputStream.flush();
byteArrayOutputStream.close();
byte[] result = byteArrayOutputStream.toByteArray();
To save on memory I'd advise you to write to a BufferedOutputStream instead of trying to get the bytes from the stream into a data structure. The android device is likely to run out of memory for large zip files.
You might be able to avoid the trouble of converting Binary by adding options to your request.
In NodeJS I specify the responseType as arraybuffer
const res = await axios.get('/routToThat/file', {
headers: {
Accept: 'application/zip',
},
responseType: 'arraybuffer',
});
So instead of receiving the server response as a Binary string:
A#B�ArE⏾�7�ϫ���f�걺N�����Yg���o_M^�D�T�U X_���e?� hi\...
I get a Buffer:
Buffer(22781691) [80, 75, 3, …]
NOTE: In my case the response I get is already a ZIP file.
More details on this NodeJS answer.
https://stackoverflow.com/a/62460311/3645464
All I need to do is construct a BufferedInputStream from the entity. Just replace BufferedReader with a BufferedInputStream. I would recommend using ISO-8859-1 .An underlying streaming encoder to read binary data is a waste of processing power.
private class methodName extends
AsyncTask<String, Integer, byte[]> {
#Override
protected byte[] doInBackground(String... params) {
String uri = params[0];
try {
MultipartEntityBuilder entity;
File f;
FileBody fb;
entity = MultipartEntityBuilder.create();
entity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
f = new File(zipImageFile);
fb = new FileBody(f);
entity.addPart("orderFile", fb);
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(uri);
Log.e("Uploload Missing Image URL", "" + uri);
httppost.setEntity(entity.build());
HttpResponse response = httpclient.execute(httppost);
// byte[] fileBites=null;
BufferedInputStream bufferedInputStream;
ByteArrayOutputStream byteArrayOutputStream;
byte[] buffer = new byte[5 * 1024];
int numRead = -1;
while( (numRead = bufferedInputStream.read(buffer))!= -1)
{
byteArrayOutputStream.write(buffer, 0, numRead);
}
byteArrayOutputStream.flush();
byteArrayOutputStream.close();
byte[] result = byteArrayOutputStream.toByteArray();
// fileBites=stringBuffer.toString().getBytes();
// Log.e("FILE BITES", fileBites+"=>"+fileBites.length);
return ;
// return stringBuffer.toString();
} catch (Exception e) {
return e.toString().getBytes();
}
}
#Override
protected void onPostExecute(byte[] result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
Log.e("Response From Server", "" + result);
writeToFile(result);
}
}
private void writeToFile(byte[] data) {
try {
FileOutputStream fop = null;
File file;
file = new File(AppConstants.DataPath+"/products.zip");
fop = new FileOutputStream(file);
// if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
try {
fop.write(data);
} catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
}
unzipImage(AppConstants.DataPath + "/products.zip",
AppConstants.DataPath);
}catch (Exception E)
{
}
}
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
}
I need a very simple function that allows me to read the first 1k bytes of a file through FTP. I want to use it in MATLAB to read the first lines and, according to some parameters, to download only files I really need eventually. I found some examples online that unfortunately do not work. Here I'm proposing the sample code where I'm trying to download one single file (I'm using the Apache libraries).
FTPClient client = new FTPClient();
FileOutputStream fos = null;
try {
client.connect("data.site.org");
// filename to be downloaded.
String filename = "filename.Z";
fos = new FileOutputStream(filename);
// Download file from FTP server
InputStream stream = client.retrieveFileStream("/pub/obs/2008/021/ab120210.08d.Z");
byte[] b = new byte[1024];
stream.read(b);
fos.write(b);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
client.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
the error is in stream which is returned empty. I know I'm passing the folder name in a wrong way, but I cannot understand how I have to do. I've tried in many way.
I've also tried with the URL's Java classes as:
URL url;
url = new URL("ftp://data.site.org/pub/obs/2008/021/ab120210.08d.Z");
URLConnection con = url.openConnection();
BufferedInputStream in =
new BufferedInputStream(con.getInputStream());
FileOutputStream out =
new FileOutputStream("C:\\filename.Z");
int i;
byte[] bytesIn = new byte[1024];
if ((i = in.read(bytesIn)) >= 0) {
out.write(bytesIn);
}
out.close();
in.close();
but it is giving an error when I'm closing the InputStream in!
I'm definitely stuck. Some comments about would be very useful!
Try this test
InputStream is = new URL("ftp://test:test#ftp.secureftp-test.com/bookstore.xml").openStream();
byte[] a = new byte[1000];
int n = is.read(a);
is.close();
System.out.println(new String(a, 0, n));
it definitely works
From my experience when you read bytes from a stream acquired from ftpClient.retrieveFileStream, for the first run it is not guarantied that you get your byte buffer filled up. However, either you should read the return value of stream.read(b); surrounded with a cycle based on it or use an advanced library to fill up the 1024 length byte[] buffer:
InputStream stream = null;
try {
// Download file from FTP server
stream = client.retrieveFileStream("/pub/obs/2008/021/ab120210.08d.Z");
byte[] b = new byte[1024];
IOUtils.read(stream, b); // will call periodically stream.read() until it fills up your buffer or reaches end-of-file
fos.write(b);
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(inputStream);
}
I cannot understand why it doesn't work. I found this link where they used the Apache library to read 4096 bytes each time. I read the first 1024 bytes and it works eventually, the only thing is that if completePendingCommand() is used, the program is held for ever. Thus I've removed it and everything works fine.
I m using content-disposition to download pdf . When I click the download button, the complete pdf file is downloaded first and then browser shows the dialog box to save the file. I want the browser to show the process of downloading. The following is my servlet code:
String filename = "abc.pdf";
String filepath = "/pdf/" + filename;
resp.setContentType("application/pdf");
resp.addHeader("content-disposition", "attachment; filename=" + filename);
ServletContext ctx = getServletContext();
InputStream is = ctx.getResourceAsStream(filepath);
System.out.println(is.toString());
int read = 0;
byte[] bytes = new byte[1024];
OutputStream os = resp.getOutputStream();
while ((read = is.read(bytes)) != -1) {
os.write(bytes, 0, read);
}
System.out.println(read);
os.flush();
os.close();
}catch(Exception ex){
logger.error("Exception occurred while downloading pdf -- "+ex.getMessage());
System.out.println(ex.getStackTrace());
}
The progress cannot be determined without knowing the response body's content length beforehand in the client side. To let the client know about the content length, you need to set the Content-Length header in the server side.
Change the line
InputStream is = ctx.getResourceAsStream(filepath);
to
URL resource = ctx.getResource(filepath);
URLConnection connection = resource.openConnection();
response.setContentLength(connection.getContentLength()); // <---
InputStream is = connection.getInputStream();
// ...
Unrelated to the concrete problem, your exception handling is bad. Replace the line
System.out.println(ex.getStackTrace());
by
throw new ServletException(ex);