Write a binary downloaded file to disk in Java - java

I have a software that allow to write add-on in javascript files (.js) that allow to use Java function (I don't know if this is common, I never saw java call in javascript file before)
I need to download a binary file from a webserver and write it to the hard drive. I tried the following code:
baseencoder = new org.apache.commons.codec.binary.Base64();
url = new java.net.URL("https://server/file.tgz");
urlConnect = url.openConnection();
urlConnect.setDoInput(true);
urlConnect.setDoOutput(true);
urlConnect.setRequestProperty("authorization","Basic "+ java.lang.String(baseencoder.encodeBase64(java.lang.String( username + ":" + password ).getBytes())));
urlConnect.setRequestProperty("content-type","application/x-www-form-urlencoded");
is = new java.io.DataInputStream(urlConnect.getInputStream());
fstream = new FileWriter("C:\\tmp\\test.tgz");
out = new BufferedWriter(fstream);
while((data = is.read()) != -1){
out.write(data);
}
out.close();
is.close();
The resulting file is no longer a valid gzip archive. I'm sorry if I did a huge error but I'm not a programmer and don't know Java too much.

Don't use a FileWriter - that's trying to convert the data into text.
Just use FileOutputStream.
byte[] buffer = new byte[8 * 1024];
InputStream input = urlConnect.getInputStream();
try {
OutputStream output = new FileOutputStream(filename);
try {
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
} finally {
output.close();
}
} finally {
input.close();
}

I know this question is already answered, but a simpler approach is to use Apache Commons IO's IOUtils.copy() method, which can fully copy an InputStream to an OutputStream.

DataInputStream is meant for reading Java primitives, not for generic data.
It's also redundant, as urlConnect.getInputStream(); already returns an InputStream, and all InputStreams support read().
is = urlConnect.getInputStream();
P.S. This is assuming is and bis are the same variable. Otherwise, you're reading the wrong stream in the loop.

Just read about LimitInputStream sounds like it does exactly what you are doing, buffering the input stream for greater efficiency.

You can even use NIO FileChannel#transferFrom method.
URL website = new URL(urlToDownload);
try (ReadableByteChannel rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(filePath);) {
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
}
Reference link1, link2

Related

downloaded file supposed to be .png

i dont know whats wrong with my code, i try to download png from server with sambautil
if (!path.equals("")) {
SambaUtil su = new SambaUtil();
byte[] data = su.openfile(path);
log.info(path);
ByteArrayInputStream inStream = new ByteArrayInputStream(su.openfile(path));
PrintWriter outStream1 = resp.getWriter();
int bytes;
while ((bytes = inStream.read()) != -1) {
outStream1.write(bytes);
}
inStream.close();
outStream1.close();
}
the connection is right, but output data seems wrong
the output
Any idea?
That is because you are taking the bytes that make up the .PNG file and printing it out instead of saving it as a file which is what I think you want to do.
Instead of
PrintWriter outStream1 = resp.getWriter();
Replace with this
OutputStream outStream1 = new FileOutputStream("somefile.png");
Then open the 'somefile.png' and you should be able to see the image that you downloaded via Samba

Is BufferedInputStream and BufferedOutputstream different from InputStream and Outputstream

recently i had troubles working with InputStreams and OutputStreams when i was trying to implement a basic file downloader in my android application.. to elaborate things this is how i did it..
i get an InputStream object using the apache HttpClient classes then tried writing the stream to a file.. but strangely when i buffer the InputStream or the OutputStream i get an unreadable file.... this is the code..
//to make the code concise i removed exceptions and stream closing..
private void download(InputStream in,String fileName){
//if i dont use the buffered thing and read directly from in everything is ok
// same is the buffered out i had to use in/outstream
BufferedInputStream bufferedIn = new BufferedInputStream(in);
FileOutputStream fout = new FileOutputStream(new File(fileName));
BufferedOutputstream bufferedOut = new BufferedOutputstream(fout);
int read = -1;
while((read = bufferedIn.read()) != -1){
bufferedOut.write(read);
}
//close the buffers
}
You have to flush the buffered outputstream when you're done with it.
In any case you probably want to flush() your output (done implicitly by close()), but with BufferedOutputStream this is even more important than with a other OutputStreams. If you have a FileOutputStream, the only buffering performed is that of the OS. If you have a BufferedOutputStream, Java performs its own buffering on top of it.
If you use Java 7 or newer, I'd recommend to write the code like this:
try (BufferedInputStream bIn = new BufferedInputStream(in);
BufferedOutputStream bOut = new BufferedOutputStream(new FileOutputStream(fileName))) {
for (int read; ((read = bIn.read()) != -1; )
bOut.write(read);
}
In your case I suspect you were closing the FileOutputStream but not the BufferedOutputStream. Therefore the file was truncated or even empty because the data buffered in the BufferedOutputStream was not flushed.

Transmission of files through Socket or HTTP, between Android devices and desktops

I have custom socket client server data (file or text) transmission code. Now when I transfer binary files, some bytes convert onto out of range characters. So I send them in hex string. That works. But for another problem this is not the solution. This has a performance problems as well.
I took help from Java code To convert byte to Hexadecimal.
When I download images from the net, same thing happens. Some bytes change into something else. I have compared bytes by bytes.
Converting into String show ? instead of the symbol. I have tried readers and byte array input stream. I have tried all the examples on the net. What is the mistake I could be doing?
My Code to save bytes to file:
void saveFile(String strFileName){
try{
URL url = new URL(strImageRoot + strFileName);
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter(strImageDownloadPath + strFileName));
String line = null;
while ( (line = reader.readLine()) != null) {
bw.write(line);
}
}catch(FileNotFoundException fnfe){
System.out.println("FileNotFoundException occured!!!");
}catch(IOException ioe){
}catch(Exception e){
System.out.println("Exception occured : " + e);
}finally{
System.out.println("Image downloaded!!!");
}
}
i had a similar issue when i was building a Socket client server application. The bytes would be some weird characters and i tried all sorts of things to try and compare them. Then i came across a discussion where some1 pointed out to me that i should use a datainputstream, dataoutstream and let that do the conversion to and from bytes. that worked for me totally. i never touched the bytes at all.
use this code
File root = android.os.Environment.getExternalStorageDirectory();
File dir = new File (root.getAbsolutePath() + "/image");
if(dir.exists()==false) {
dir.mkdirs();
}
URL url = new URL("http://4.bp.blogspot.com/-zqJs1fVcfeY/TiZM7e-pFqI/AAAAAAAABjo/aKTtTDTCgKU/s1600/Final-Fantasy-X-Night-Sky-881.jpg");
//URL url = new URL(DownloadUrl);
//you can write here any link
File file = new File(dir,"Final-Fantasy-X-Night-Sky-881.jpg");
long startTime = System.currentTimeMillis();
//Open a connection to that URL.
URLConnection ucon = url.openConnection();
//* Define InputStreams to read from the URLConnection.
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
//* Read bytes to the Buffer until there is nothing more to read(-1).
ByteArrayBuffer baf = new ByteArrayBuffer(6000);
int current = 0;
while ((current = bis.read()) != -1) {
baf.append((byte) current);
}
//Convert the Bytes read to a String.
FileOutputStream fos = new FileOutputStream(file);
fos.write(baf.toByteArray());
fos.flush();
fos.close();
You should take the help of this link: How to encode decode in base64 in Android.
You can send byte array obtained from a file as string by encoding into Base64. This reduces the amount of data transmitted as well.
At the receiving end just decode the string using Base64 and obtain byte array.
Then you can use #Deepak Swami's solution to save bytes in file.
I recently found out that PHP service APIs do not know about what is byte array. Any String can be byte stream at the same time, so the APIs expect Base64 string in the request parameter. Please see the posts:
String to byte array in php
Passing base64 encoded strings in URL
Hence Base64 has quite importance as also it allows you to also save byte arrays in preferences, and increases performance if you have to send file data across network using Serialization.
Happy Coding :-)

Using PrintWriter while downloading a file

I have a requirement, where i need to process a set of files and create a compressed zip file out of it and then use it for download. I am using a Servlet for downloading that file, but the download takes quite sometime. So i want the user to know that the servlet is processing the request through a print writer output messsage instead of showing him a blank screen.But everytime i use a printwriter to write something to the screen, the message takes a lot of time to show on the screen and the file doesnt download.
How can i achieve this? Any ides?
Thanks.
Here's my code
OutputStream oStream = null;
DataInputStream dInput = null;
File file = new File(("PATH"));
int length = 0;
try{
DownloadServerLogs.processLogs();
oStream = res.getOutputStream();
res.setContentType("application/zip");
res.setContentLength((int)file.length());
res.setHeader("Content-Disposition",
"attachment;filename=\"" + file.getName() + "\"" );
byte[] bbuf = new byte[BYTES_DOWNLOAD];
dInput = new DataInputStream(new FileInputStream(file));
while ((dInput != null) && ((length = dInput.read(bbuf)) != -1))
{
oStream.write(bbuf,0,length);
}
dInput.close();
oStream.flush();
oStream.close();
}catch(Exception e){
Utility.getLogger().error(e.getMessage(), e);
}
I guess its better to display the message to the client by using something like Javascript (assuming you are using AJAX to invoke the servlet).
Well, it's probably not that safe to do it that way. I'd have a look at the answer below. Not that it's your exact problem, but might be similar.
Most efficient way to create InputStream from OutputStream
Effectively, you are reading and writing on the same thread and my guess is that with the addition of the PrintWriter you are getting deadlocked somewhere.

Java urlConnection, saving audio file to server?

I've seen examples with text files but is saving an audio file directly to a server done the same way with URLConnection?
Yes, the same. Although make sure you use a binary output stream to write the content to disk.
Something like:
URLConnection conn = new URL("http://www.gravatar.com/avatar/fd9e8761fad999a1bf1e095fc8f53ffe?s=32&d=identicon&r=PG")
.openConnection();
InputStream is = conn.getInputStream();
FileOutputStream outstream = new FileOutputStream("/tmp/myfile");
byte[] buffer = new byte[4096];
int len;
while ((len = is.read(buffer)) > 0) {
outstream.write(buffer, 0, len);
}
outstream.close();
is.close();
The example uses your gravatar, but same difference.

Categories