首页 > 代码库 > Java 实现多线程文件下载(HTTP)

Java 实现多线程文件下载(HTTP)

实现原理:

 用httpConnection.setRequestProperty("RANGE", "bytes= xxx-xxx");获取指定的数据块

用RandomAccessFile实现文件随机访问,写入指定数据块到文件.

关键事项:获取远程文件大小,根据文件大小确定下载线程个数(可固定线程数,也可固定每个线程下载数据块大小,用户自己决定).

 

package org.hundred.multithreads; import java.io.File;import java.io.IOException;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL; /** * 文件下载管理类 */public class DownLoadManager {    /**     * 每个线程下载的字节数     */    static final long unitSize = 1000 * 1024;     /**     * 启动多个线程下载文件     */    public void doDownload(String remoteFileUrl)            throws IOException {               String fileName = new URL(remoteFileUrl).getFile();        fileName = fileName.substring(fileName.lastIndexOf("/")+1,fileName.length()).replace("%20", " ");                   long fileSize = this.getRemoteFileSize(remoteFileUrl);         if(fileSize == 0){            return;        }               this.createFile(fileName, fileSize);         long threadCount = fileSize / unitSize;        System.out.println("共启动 "                + (fileSize % unitSize == 0 ? threadCount : threadCount + 1)                + " 个线程");         long offset = 0;        if (fileSize <= unitSize) {// 如果远程文件尺寸小于等于unitSize            DownloadThread downloadThread = new DownloadThread(remoteFileUrl,                    fileName, offset, fileSize);            downloadThread.start();        } else {// 如果远程文件尺寸大于unitSize            for (int i = 1; i <= threadCount; i++) {                DownloadThread downloadThread = new DownloadThread(                        remoteFileUrl, fileName, offset, unitSize);                downloadThread.start();                 offset = offset + unitSize;            }            if (fileSize % unitSize != 0) {// 如果不能整除,则需要再创建一个线程下载剩余字节                DownloadThread downloadThread = new DownloadThread(                        remoteFileUrl, fileName, offset, fileSize                                - unitSize * threadCount);                downloadThread.start();             }        }     }     /**     * 获取远程文件尺寸     */    private long getRemoteFileSize(String remoteFileUrl) throws IOException {         long fileSize = 0;        HttpURLConnection httpConnection = (HttpURLConnection) new URL(                remoteFileUrl).openConnection();               httpConnection.setRequestMethod("HEAD");               int responseCode = httpConnection.getResponseCode();        if(responseCode >= 400){            System.out.println("Web服务器响应错误!");            return 0;        }               String sHeader;        for(int i=1;;i++){            sHeader = httpConnection.getHeaderFieldKey(i);            if(sHeader != null && sHeader.equals("Content-Length")){                System.out.println("文件大小ContentLength:"+httpConnection.getContentLength());                fileSize = Long.parseLong(httpConnection.getHeaderField(sHeader));                break;            }        }         return fileSize;    }     /**     * 创建指定大小的文件     */    private void createFile(String fileName, long fileSize) throws IOException {        File newFile = new File(fileName);        RandomAccessFile raf = new RandomAccessFile(newFile, "rw");         raf.setLength(fileSize);         raf.close();    } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////package org.angus.multithreads; import java.io.BufferedInputStream;import java.io.File;import java.io.IOException;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL; /** * 负责文件下载的类 */public class DownloadThread extends Thread {    /**     * 待下载的文件     */    private String url = null;     /**     * 本地文件名     */    private String fileName = null;     /**     * 偏移量     */    private long offset = 0;     /**     * 分配给本线程的下载字节数     */    private long length = 0;     /**     * @param url 下载文件地址     * @param fileName 另存文件名     * @param offset 本线程下载偏移量     * @param length 本线程下载长度     *     * @author Angus.wang     * */    public DownloadThread(String url, String file, long offset, long length) {        this.url = url;        this.fileName = file;        this.offset = offset;        this.length = length;        System.out.println("偏移量=" + offset + ";字节数=" + length);    }     public void run() {        try {            HttpURLConnection httpConnection = (HttpURLConnection) new URL(                    this.url).openConnection();             httpConnection.setRequestMethod("GET");            httpConnection.setRequestProperty("RANGE", "bytes=" + this.offset                    + "-" + (this.offset + this.length - 1));                       System.out.println("RANGE bytes=" + this.offset + "-" + (this.offset + this.length - 1));                       BufferedInputStream bis = new BufferedInputStream(httpConnection                    .getInputStream());             byte[] buff = new byte[1024];            int bytesRead;            File newFile = new File(fileName);            RandomAccessFile raf = new RandomAccessFile(newFile, "rw");                                  while ((bytesRead = bis.read(buff, 0, buff.length)) != -1) {                raf.seek(this.offset);                raf.write(buff, 0, bytesRead);                               this.offset = this.offset + bytesRead;            }                       raf.close();            bis.close();        } catch (IOException ioe) {            ioe.printStackTrace();        }     } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////package org.angus.multithreads; /** * 多线程文件下载测试 * */public class FileDownloadTest {     /**     * @param args     */    public static void main(String[] args) {        try{            String remoteFileUrl = "http://dl.maxthon.cn/cn/mx2/mx_2.5.1.4751cn.exe";                       DownLoadManager downLoadManager = new DownLoadManager();                       downLoadManager.doDownload(remoteFileUrl);        }catch(Exception e){            e.printStackTrace();        }            } }

 

Java 实现多线程文件下载(HTTP)