Tom
Tom

Reputation: 2847

Issue of download picture from internet using java code

The following code is not working:

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class DownloadFile extends Thread {

    URL url;
    long startPos;
    long endPos;
    int length;
    public static ExecutorService pool = Executors.newCachedThreadPool();

    public DownloadFile(URL url, long startPos, long endPos, int length) {
        this.url = url;
        this.startPos = startPos;
        this.endPos = endPos;
        this.length = length;
    }

    public static void main(String[] args) {
        try {
            download(new URL(
                    "http://hiphotos.baidu.com/dazhu1115/pic/item/fb8eccffa223a373d6887dfc.jpg"));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void download(URL url) throws IOException {
        String fileName = url.getFile();
        final long size = 8096;
        if (fileName.equals("")) {
            throw new IOException("download webfile \"" + fileName
                    + "\" failed");
        }
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        long total = con.getContentLength();
        System.out.println("file size is " + total);
        con.disconnect();
        if (total <= size) {
            // con = (HttpURLConnection) url.openConnection();
            // con.connect();
            // in = con.getInputStream();
            // return download(fileName, in);
            // con.disconnect();
        } else {
            long part = total % size != 0 ? total / size + 1 : total / size;
            long len;
            byte[] b = null;
            for (int i = 0; i < part; i++) {
                len = i != part - 1 ? size : total % size;
                DownloadFile dl = new DownloadFile(url, size * i, size
                        * (i + 1), (int) len);
                pool.execute(dl);
            }
        }
    }

    public void run() {
        byte[] b = new byte[length];
        HttpURLConnection con;
        try {
            con = (HttpURLConnection) url.openConnection();
            con.setAllowUserInteraction(true);
            con.setReadTimeout(30000);
            con.setRequestProperty("RANGE", "bytes=" + startPos + "-" + endPos);
            // con.setRequestProperty("GET", fileName + " HTTP/1.1");
            // con.setRequestProperty("Accept","image/gif,image/x-xbitmap,application/msword");
            // con.setRequestProperty("Connection", "Keep-Alive");
            con.connect();
            /*
             * in = con.getInputStream(); DataInputStream dis = new
             * DataInputStream(in);
             */
            BufferedInputStream bis = new BufferedInputStream(
                    con.getInputStream());
            int wlen = bis.read(b, 0, length);
            RandomAccessFile oSavedFile = new RandomAccessFile("D:/bbb.jpg",
                    "rw");
            oSavedFile.seek(startPos);
            oSavedFile.write(b, 0, wlen);
            // con.disconnect();
            bis.close();
            oSavedFile.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

The size of downloaded picture is correct,but can't view the image of this picture properly. I don't know where the trick is. The following is the image I downloaded enter image description here

Issue resolved, changed my code to :

package com.tom.labs;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class DownloadFile extends Thread {

    URL url;
    long startPos;
    long endPos;
    final static int bufferSize = 1024 * 3;
    public static ExecutorService pool = Executors.newCachedThreadPool();

    public DownloadFile(URL url, long startPos, long endPos) {
        this.url = url;
        this.startPos = startPos;
        this.endPos = endPos;
    }

    public static void main(String[] args) {
        try {
            download(new URL("http://hiphotos.baidu.com/dazhu1115/pic/item/fb8eccffa223a373d6887dfc.jpg"));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void download(URL url) throws IOException {
        String fileName = url.getFile();
        final long size = 8096;
        if (fileName.equals("")) {
            throw new IOException("download webfile \"" + fileName + "\" failed");
        }
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        long total = con.getContentLength();
        System.out.println("file size is " + total);
        con.disconnect();
        if (total <= size) {

        } else {
            long part = total % size != 0 ? total / size + 1 : total / size;
            long len;
            byte[] b = null;
            for (int i = 0; i < part; i++) {
                len = i != part - 1 ? size : total % size;
                long startPos = size * i;
                long endPos = startPos + len - 1;
                con = (HttpURLConnection) url.openConnection();
                con.setAllowUserInteraction(true);
                con.setReadTimeout(30000);
                con.setRequestProperty("RANGE", "bytes=" + startPos + "-" + endPos);
                System.out.println("Request Data from " + startPos + " to " + endPos);
                con.connect();

                DownloadFile task = new DownloadFile(url,startPos,endPos);
                pool.execute(task);
            }
        }
    }

    public void run() {
        byte[] b = new byte[bufferSize];
        HttpURLConnection con;
        try {
            con = (HttpURLConnection) url.openConnection();
            con.setAllowUserInteraction(true);
            con.setReadTimeout(30000);
            con.setRequestProperty("RANGE", "bytes=" + startPos + "-" + endPos);
            con.connect();
            BufferedInputStream bis = new BufferedInputStream(con.getInputStream());
            RandomAccessFile oSavedFile = new RandomAccessFile("D:/bbb.jpg", "rw");
            oSavedFile.seek(startPos);
            System.out.println("Request Data from " + startPos + " to " + endPos);
            while (startPos < endPos) {
                int wlen = bis.read(b, 0, bufferSize);
                oSavedFile.write(b, 0, wlen);
                startPos += wlen;
            }
            bis.close();
            oSavedFile.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Upvotes: 0

Views: 1637

Answers (3)

andih
andih

Reputation: 5603

The BufferedIntpuStream.read method returns if there are no more bytes available so you have to loop until you have written the whole block size.

Here is a Fix for your Problem:

       BufferedInputStream bis = new BufferedInputStream(
                con.getInputStream());


        RandomAccessFile oSavedFile = new RandomAccessFile("D:/bbb.jpg",
                "rw");            
        oSavedFile.seek(startPos);
        int wlen = 0;
        while (wlen < length) {
            int read = bis.read(b, 0, length);
            wlen += read;
            oSavedFile.write(b, 0, read);
        }

Upvotes: 1

Abhilash
Abhilash

Reputation: 792

I have added some logging statements locally in your code. Below is the log.

file size is 69635
Requesting data from position 0 to 8096
Requesting data from position 8096 to 16192
Requesting data from position 32384 to 40480
Requesting data from position 24288 to 32384
Requesting data from position 16192 to 24288
Requesting data from position 48576 to 56672
Requesting data from position 40480 to 48576
Requesting data from position 64768 to 72864
Requesting data from position 56672 to 64768
Writing data starting at 0
Writing data starting at 16192
Writing data starting at 24288
Writing data starting at 48576
Writing data starting at 40480
Writing data starting at 64768
Writing data starting at 56672
Writing data starting at 32384
Writing data starting at 8096

See the issue is with multithreading. The program is writing data in the wrong order to a file ending up as a corrupted file. Hope this is clear enough. Is this a homework?

Upvotes: 0

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285403

I've done something like this to extract files:

     String imgPath = "/* path to the URL on the internet */ "; 
     String imgFilePath = " /* path to file on disk */ ";

     URL imgUrl;
     try {
        imgUrl = new URL(imgPath);
        ReadableByteChannel rbc = Channels.newChannel(imgUrl.openStream());
        FileOutputStream fos = new FileOutputStream(imgFilePath);
        setState(EXTRACTING + imgFilePath);
        fos.getChannel().transferFrom(rbc, 0, 1 << 24);

     } catch (MalformedURLException e) {
        e.printStackTrace();
     } catch (FileNotFoundException e) {
        e.printStackTrace();
     } catch (IOException e) {
        e.printStackTrace();
     }

Upvotes: 1

Related Questions