Write a binary downloaded file to disk in Java
Asked Answered
N

5

8

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.

Noblenobleman answered 25/9, 2009 at 13:24 Comment(0)
E
34

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();
}
Elwood answered 25/9, 2009 at 13:24 Comment(2)
Also, you'll want to use the correct test condition in your while loop: while((data = is.read()) != null){ ... }.Epiboly
Thanks using a FileOutputStream works (i still use only a simple read() because it seems that it's not possible to use a byte buffer in javascript as it's not an object.Noblenobleman
R
9

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.

Recruitment answered 8/5, 2012 at 21:27 Comment(0)
T
2

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.

Tumblebug answered 25/9, 2009 at 13:32 Comment(1)
Nice Information! Interesting to learn that despite what the naming suggest DataInputStream isn't for generic data..!Sooksoon
A
0

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

Aster answered 20/7, 2012 at 0:47 Comment(0)
S
0

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

Selenium answered 9/7, 2022 at 10:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.