java多线程实现文件下载

本文实例为大家分享了java多线程实现文件下载的具体代码,供大家参考,具体内容如下

1、DownloadManager类

import java.io.File;
import java.io.FileInputStream;
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.ArrayList;
import java.util.List;

public class DownloadManager implements Runnable {
 // 保存路径
 private String savePath;
 // 总的下载线程数
 private int threadNum;
 // 下载的链接地址
 private String urlFile;
 // 是否下载开始
 private boolean isStarted;
 // 用于监视何时合并文件存放Thread的list
 private List<DownloadThread> downloadList = new ArrayList<DownloadThread>();

 public DownloadManager(String savePath, int threadNum, String urlFile) {
 super();
 this.savePath = savePath;
 this.threadNum = threadNum;
 this.urlFile = urlFile;
 }

 // 最终调用线程下载。本线程中调用分线程。
 public void action() {
 new Thread(this).start();
 }

 public void run() {
 long t1 = System.currentTimeMillis();
 System.out.println(t1);
 // 如果没有下载 , 就开始 , 并且将已经下载的变量值设为true
 if (!isStarted) {
 startDownload();
 isStarted = true;
 }
 while (true) {
 // 初始化认为所有线程下载完成,逐个检查
 boolean finish = true;
 // 如果有任何一个没完成,说明下载没完成,不能合并文件
 for (DownloadThread thread : downloadList) {
 if (!thread.isFinish()) {
 finish = false;
 break;
 }
 }
 // 全部下载完成才为真
 if (finish) {
 // 合并文件
 mergeFiles();
 // 跳出循环 , 下载结束
 break;
 }
 // 休息一会 , 减少cpu消耗
 try {
 Thread.sleep(1000);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }
 long t2 = System.currentTimeMillis();
 System.out.println(t2);
 System.out.println("下载用时:" + (t2 -t1));
 }

 public void startDownload() {
 // 得到每个线程开始值 , 下载字节数大小
 int[][] posAndLength = getPosAndLength();
 // 根据下载信息创建每个下载线程,并且启动他们。
 for (int i = 0; i < posAndLength.length; i++) {
 int pos = posAndLength[i][0];
 int length = posAndLength[i][1];
 DownloadThread downloadThread = new DownloadThread(i + 1, length,
 pos, savePath, urlFile);
 new Thread(downloadThread).start();
 downloadList.add(downloadThread);
 }
 }

 /**
 * 获得文件大小
 *
 * @return 文件大小
 */
 public long getFileLength() {
 System.out.println("获得文件大小 start......");
 HttpURLConnection conn = null;
 long result = 0;
 try {
 URL url = new URL(urlFile);
 conn = (HttpURLConnection) url.openConnection();
 // 使用Content-Length头信息获得文件大小
 result = Long.parseLong(conn.getHeaderField("Content-Length"));
 } catch (MalformedURLException e) {
 e.printStackTrace();
 } catch (IOException e) {
 e.printStackTrace();
 } finally {
 if (conn != null) {
 conn.disconnect();
 }
 }
 System.out.println("获得文件大小 end......" + result);
 return result;
 }

 // 具体细节求出每个线程的开始位置和文件下载大小
 public int[][] getPosAndLength() {
 int[][] result = new int[threadNum][2];
 int fileLength = (int) getFileLength();
 int every = fileLength % threadNum == 0 ? fileLength / threadNum
 : fileLength / threadNum + 1;
 for (int i = 0; i < result.length; i++) {
 int length = 0;
 if (i != result.length - 1) {
 length = every;
 } else {
 length = fileLength - i * every;
 }
 result[i][0] = i * every;
 result[i][1] = length;
 }
 return result;
 }

 // 合并文件
 public void mergeFiles() {
 System.out.println("合并文件 start......");
 OutputStream out = null;
 try {
 out = new FileOutputStream(savePath);
 for (int i = 1; i <= threadNum; i++) {
 InputStream in = new FileInputStream(savePath + i);
 byte[] bytes = new byte[2048];
 int read = 0;
 while ((read = in.read(bytes)) != -1) {
 out.write(bytes, 0, read);
 out.flush();
 }
 if (in != null) {
 in.close();
 new File(savePath + i).delete();
 }
 }
 } catch (Exception e) {
 e.printStackTrace();
 } finally {
 if (out != null) {
 try {
 out.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 System.out.println("合并文件 end......");
 }

 public String getSavePath() {
 return savePath;
 }

 public void setSavePath(String savePath) {
 this.savePath = savePath;
 }

 public int getThreadNum() {
 return threadNum;
 }

 public void setThreadNum(int threadNum) {
 this.threadNum = threadNum;
 }

 public String getUrlFile() {
 return urlFile;
 }

 public void setUrlFile(String urlFile) {
 this.urlFile = urlFile;
 }

 public boolean isStarted() {
 return isStarted;
 }

 public void setStarted(boolean isStarted) {
 this.isStarted = isStarted;
 }

 public List<DownloadThread> getDownloadList() {
 return downloadList;
 }

 public void setDownloadList(List<DownloadThread> downloadList) {
 this.downloadList = downloadList;
 }
}

2、DownloadThread类

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class DownloadThread implements Runnable {
 // 当前第几个线程 , 用于给下载文件起名 file1 file2 file3 ...
 private int whichThread;
 // 监听单一线程下载是否完成
 private boolean isFinish;
 // 本线程要下载的文件字节数
 private int length;
 // 本线程向服务器发送请求时输入流的首位置
 private int startPosition;
 // 保存的路径
 private String savePath;
 // 要下载的文件 , 用于创建连接
 private String url;

 public void run() {
 HttpURLConnection conn = null;
 InputStream in = null;
 OutputStream out = null;
 try {
 System.out.println("正在执行的线程:" + whichThread);
 URL fileUrl = new URL(url);
 // 与服务器创建连接
 conn = (HttpURLConnection) fileUrl.openConnection();
 // 下载使用get请求
 conn.setRequestMethod("GET");
 // 告诉服务器 , 我是火狐 , 不要不让我下载。
 conn.setRequestProperty(
 "User-Agent",
 "Firefox Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3");
 // 这里是设置文件输入流的首位置
 conn.setRequestProperty("Range", "bytes=" + startPosition + "-");
 // 与服务器创建连接
 conn.connect();
 // 获得输入流
 in = conn.getInputStream();
 // 在硬盘上创建file1 , file2 , ...这样的文件 , 准备往里面写东西
 out = new FileOutputStream(savePath + whichThread);
 // 用于写入的字节数组
 byte[] bytes = new byte[4096];
 // 一共下载了多少字节
 int count = 0;
 // 单次读取的字节数
 int read = 0;
 while ((read = in.read(bytes)) != -1) {
 // 检查一下是不是下载到了本线程需要的长度
 if (length - count < bytes.length) {
 // 比如说本线程还需要900字节,但是已经读取1000
 // 字节,则用要本线程总下载长度减去
 // 已经下载的长度
 read = length - count;
 }
 // 将准确的字节写入输出流
 out.write(bytes, 0, read);
 // 已经下载的字节数加上本次循环字节数
 count = count + read;
 // 如果下载字节达到本线程所需要字节数,消除循环,
 // 停止下载
 if (count == length) {
 break;
 }
 }
 // 将监视变量设置为true
 isFinish = true;
 } catch (Exception e) {
 e.printStackTrace();
 } finally {
 // 最后进行输入、输出、连接的关闭
 if (in != null) {
 try {
 in.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 if (out != null) {
 try {
 out.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 if (conn != null) {
 conn.disconnect();
 }
 }
 }

 public int getStartPosition() {
 return startPosition;
 }

 public void setStartPosition(int startPosition) {
 this.startPosition = startPosition;
 }

 public String getUrl() {
 return url;
 }

 public void setUrl(String url) {
 this.url = url;
 }

 public int getWhichThread() {
 return whichThread;
 }

 public void setWhichThread(int whichThread) {
 this.whichThread = whichThread;
 }

 public int getLength() {
 return length;
 }

 public void setLength(int length) {
 this.length = length;
 }

 public String getSavePath() {
 return savePath;
 }

 public void setSavePath(String savePath) {
 this.savePath = savePath;
 }

 public DownloadThread(int whichThread, int length, int startPosition,
 String savePath, String url) {
 super();
 this.whichThread = whichThread;
 this.length = length;
 this.startPosition = startPosition;
 this.savePath = savePath;
 this.url = url;
 }

 public DownloadThread() {
 super();
 }

 public boolean isFinish() {
 return isFinish;
 }

 public void setFinish(boolean isFinish) {
 this.isFinish = isFinish;
 }
}

3、TestDownload测试类

public class TestDownload {

 public static void main(String[] args) {
 DownloadManager downloadManager = new DownloadManager("d:/upload/09018417.zip" , 5 , "http://10.1.2.65:8080/cetvossFront/09018417.zip");
 downloadManager.action();
 }
}

代码已经测试可以运行!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java Web实现文件下载和乱码处理方法

    文件上传和下载是web开发中常遇到的问题,这几天在做一个项目又用到了文件下载,之前也零零散散记了些笔记,今天来做一下整理.文件上传还有待进一步测试,这里先说一下文件下载. 一.文件下载处理流程 文件下载处理流程其实很清晰,即: 1.根据文件名或者文件路径定位文件,具体的策略主要根据自己的需求,总之需要系统能找到的文件全路径. 2.获取输入流,从目标文件获取输入流. 3.获取输出流,从response中获取输出流. 4.从输入流读入文件,通过输出流输出文件.这是真正的下载执行过程. 5.关闭IO流

  • java实现文件下载的两种方式

    本文实例为大家分享了java实现文件下载的具体代码,供大家参考,具体内容如下 public HttpServletResponse download(String path, HttpServletResponse response) { try { // path是指欲下载的文件的路径. File file = new File(path); // 取得文件名. String filename = file.getName(); // 取得文件的后缀名. String ext = filena

  • java使用http实现文件下载学习示例

    复制代码 代码如下: package com.hongyuan.test; import java.io.File;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 Web端程序实现文件下载的方法分享

    Web文件下载有两种,一种是文件在网站目录下,在浏览器中直接输入文件路径即可下载,如http://www.xxx.com/file.zip.另外一种是文件不在网站目录下或者文件是动态生成的(导出报表或者导出excel等),这种情况需要通过response的OutputStream实现文件的下载.DownloadUtils是一个Java Web文件下载工具类,提供多种静态方法实现文件下载. package com.rhui.util; import java.io.BufferedInputStr

  • java实现FTP文件上传与文件下载

    本文实例为大家分享了两种java实现FTP文件上传下载的方式,供大家参考,具体内容如下 第一种方式: package com.cloudpower.util; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import sun.net.TelnetInputStream; import sun.net.TelnetO

  • JavaEE实现文件下载

    我们先来看一个最简单的文件下载的例子: 复制代码 代码如下: package com.yyz.response;  import java.io.FileInputStream;  import java.io.IOException;  import java.io.OutputStream;  import javax.servlet.ServletException;  import javax.servlet.http.HttpServlet;  import javax.servlet

  • 详解Java文件下载的几种实现方式

    Java文件下载的几种方式,具体如下: public HttpServletResponse download(String path, HttpServletResponse response) { try { // path是指欲下载的文件的路径. File file = new File(path); // 取得文件名. String filename = file.getName(); // 取得文件的后缀名. String ext = filename.substring(filena

  • java web项目实现文件下载实例代码

    复制代码 代码如下: File file = new File(path);// path是根据日志路径和文件名拼接出来的    String filename = file.getName();// 获取日志文件名称    InputStream fis = new BufferedInputStream(new FileInputStream(path));    byte[] buffer = new byte[fis.available()];    fis.read(buffer); 

  • Java Web项目中实现文件下载功能的实例教程

    需求:实现一个具有文件下载功能的网页,主要下载压缩包和图片 两种实现方法: 一:通过超链接实现下载 在HTML网页中,通过超链接链接到要下载的文件的地址 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h1>通过链接下载文件&

  • Java实现ftp文件上传下载解决慢中文乱码多个文件下载等问题

    废话不多说了,直接给大家贴代码了,具体代码如下所示: //文件上传 public static boolean uploadToFTP(String url,int port,String username,String password,String path,String filename,InputStream input) { boolean success=false; FTPClient ftp=new FTPClient();//org.apache.commons.net.ftp

随机推荐