基于HTTP的单线程文件下载功能实现

思路

  1. 使用http请求远程文件地址
  2. 从响应体中获取文件头信息
  3. 读取响应体中的输入流,并写入本地文件输出流中

代码实现

package org.hanmeis;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Logger;

/**
 * Created by zhao.wu on 2016/12/7.
 * 单线程下载
 * 使用方法:SingleDownloader [url]
 */
public class SingleDownloader {
    private static Logger logger = Logger.getLogger("SingleDownloader");

    public static void main(String[] args) throws IOException {
        String url;
        if(args.length<1){
            System.out.print("输入下载地址:");
            url = new Scanner(System.in).nextLine();
        }else {
            url = args[0];
        }

        //校验参数合法性 略

        SingleDownloader singleDownloader = new SingleDownloader(url);
        singleDownloader.connectServer();
        singleDownloader.startDownload();
    }

    private URL url;
    private String fileName;
    private long fileSize;
    private long preSize;
    private long currentSize;
    private InputStream is;
    private OutputStream os;
    private Timer timer = new Timer();

    private SingleDownloader(){
        logger.info("新任务加入下载队列......");
    }

    private SingleDownloader(String url) throws MalformedURLException {
        this();
        this.url = new URL(url);
    }

    /**
     * 连接远程服务器,并获取文件信息:大小,文件名
     * @throws IOException
     */
    private void connectServer() throws IOException {
        logger.info(String.format("连接服务器:%s://%s",url.getProtocol(),url.getHost()));

        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setConnectTimeout(10*1000);

        this.fileSize = Long.parseLong(connection.getHeaderField("Content-Length"));

        String[] temp = url.getFile().split("/");
        if(temp.length!=0) {
            this.fileName = temp[temp.length - 1];
        }

        this.is =  connection.getInputStream();
        this.os = new FileOutputStream(this.fileName);

        logger.info(String.format("文件名:%s  大小:%.2fM", this.fileName, this.fileSize*1.0/1024/1024));
    }

    /**
     * 下载过程
     * @throws IOException
     */
    private void startDownload() throws IOException {

        logger.info(String.format("开始下载:%s",fileName));
        info();

        byte[] bs = new byte[5120];
        int len;
        while((len = is.read(bs))>0){
            os.write(bs);
            this.currentSize += len;
        }
        is.close();
        os.close();
        timer.cancel();
        logger.info(String.format("完成下载:%s",fileName));
    }

    /**
     * 定时计算下载状态
     */
    private void info(){
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                long tempC = currentSize;
                long tempSize = tempC-preSize;
                preSize = tempC;
                double percent = (tempC*100.0)/fileSize;
                double speed = (tempSize*1.0)/1024/3;
                logger.info(String.format("文件:%s 已完成:%.2f%%  速率:%.2fkb/s",fileName, percent, speed));
            }
        },0, 3000);
    }
}
posted @ 2016-12-08 19:33  吴昭  阅读(111)  评论(0编辑  收藏  举报