Artemkller545
Artemkller545

Reputation: 999

Java - downloading image by bytes downloads a broken image

Hello I was curious on how data can be downloaded in java, so I looked through few methods and decided to use BufferedInputStream.

Now when I download, I download the file by 1024 bytes burst, and everytime it downloads 1kb I concat the temp array to the main data array.tH

I use this concat method:

public static byte[] concat(byte[] data, byte[] bytes) {
     byte[] result = Arrays.copyOf(data, data.length + bytes.length);
     System.arraycopy(bytes, 0, result, data.length, bytes.length);
     return result;
}

This is my download process:

    URL target = new URL ("http://freshhdwall.com/wp-content/uploads/2014/08/Image-Art-Gallery.jpg");
    URLConnection t = target.openConnection();
    t.setRequestProperty("User-Agent", "NING/1.0");
    t.connect();
    
    BufferedInputStream stream = new BufferedInputStream(t.getInputStream());
    
    final byte[] bytes = new byte[1024];
    int count;
    
    byte[] data = new byte[0];
    
    while ( (count = stream.read(bytes, 0, bytes.length)) != -1) {
        System.out.println(count);
        data = concat(data, bytes);
    }

Now after downloading, I convert the bytes array to BufferedImage using ByteArrayInputStream:

    InputStream s = new ByteArrayInputStream(data);
    BufferedImage m = ImageIO.read(s);

And then I display the result:

    JFrame j = new JFrame();
    j.add(new JLabel(new ImageIcon(m)));
    j.pack();
    j.setVisible(true);

Now the result image looks like this:

img
(source: gyazo.com)

As you see, the image looks broken, missing bytes when downloading. This is the real image:

img http://freshhdwall.com/wp-content/uploads/2014/08/Image-Art-Gallery.jpg

What did I do wrong that it displays the image like that?

Upvotes: 1

Views: 676

Answers (1)

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279880

On each loop iteration, you potentially read less than bytes.length bytes. As such, you can't use the full length of the array. You need to use exactly that part that was actually read.

One solution is to use

while ((count = stream.read(bytes, 0, bytes.length)) != -1) {
    System.out.println(count); // this should hint at this
    data = concat(data, bytes, count); // use the count
}

and

public static byte[] concat(byte[] data, byte[] bytes, int count) {
    byte[] result = Arrays.copyOf(data, data.length + count);
    System.arraycopy(bytes, 0, result, data.length, count);
    return result;
}

so as to only copy over the bytes you've actually received.

Consider using some of the solutions here. They are probably more efficient or, at least, more readable.

Upvotes: 2

Related Questions