Java利用URL实现文件下载

利用URL(网络资源统一定位符),我们可以进行文件的定位和下载,

如果我们想让下载速度提高一些,我们通常有以下方法:

1.提高网络带宽,提升网络速度

2.开通网站vip,实现高速下载或上传

3.新增下载线程,实现多线程同时下载

通常情况下,方法1是作为一个普通程序员是无法实现的,因为网络带宽是由网络运行商限定,

除非我们多交钱或者是开通专用通道(vpn),

方法2的话,也是需要花钱,比如某云盘,只要你充值会员,就可以实现高速下载或是上传文件,

其实,我说那么多都是废话,我想分享给大家的就是方法3,利用URL进行多线程下载,

由于代码注释我都写的很明了,所有直接上代码了,下面就是主类代码,不需引入三方jar包,可直接运行,

运行该类可以从hao123网站下载一个输入法,当然了,URL地址可以随便更改。

package com.yc.net;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;

/**
 * 多线程下载
 * 
 * @author jam
 *
 */
public class ThreadDownloader {

	public static void main(String[] args) throws IOException, InterruptedException {
		// 记录开始下载的时间
		long begin_time = new Date().getTime();

		// 创建一个URL链接
		// 从hao123网站下载一个输入法,下面是下载地址
		URL url = new URL("http://softdown1.hao123.com/hao123-soft-online-bcs/soft/2017_09_29_jpwb2017qj.exe");

		// 获取连接
		URLConnection conn = url.openConnection();

		// 获取文件全路径
		String fileName = url.getFile();

		// 获取文件名
		fileName = fileName.substring(fileName.lastIndexOf("/"));

		System.out.println("开始下载>>>");

		// 获取文件大小
		int fileSize = conn.getContentLength();

		System.out.println("文件总共大小:" + fileSize + "字节");

		// 设置分块大小
		int blockSize = 1024 * 1024;
		// 文件分块的数量
		int blockNum = fileSize / blockSize;

		if ((fileSize % blockSize) != 0) {
			blockNum += 1;
		}

		System.out.println("分块数->线程数:" + blockNum);

		Thread[] threads = new Thread[blockNum];
		for (int i = 0; i < blockNum; i++) {

			// 匿名函数对象需要用到的变量
			final int index = i;
			final int finalBlockNum = blockNum;
			final String finalFileName = fileName;

			// 创建一个线程
			threads[i] = new Thread() {
				public void run() {
					try {

						// 重新获取连接
						URLConnection conn = url.openConnection();
						// 重新获取流
						InputStream in = conn.getInputStream();
						// 定义起始和结束点
						int beginPoint = 0, endPoint = 0;

						System.out.print("第" + (index + 1) + "块文件:");
						beginPoint = index * blockSize;

						// 判断结束点
						if (index < finalBlockNum - 1) {
							endPoint = beginPoint + blockSize;
						} else {
							endPoint = fileSize;
						}

						System.out.println("起始字节数:" + beginPoint + ",结束字节数:" + endPoint);

						// 将下载的文件存储到一个文件夹中
						//当该文件夹不存在时,则新建
						File filePath = new File("E:/temp_file/");
						if (!filePath.exists()) {
							filePath.mkdirs();
						}
						
						FileOutputStream fos = new FileOutputStream(new File("E:/temp_file/", finalFileName + "_" + (index + 1)));

						// 跳过 beginPoint个字节进行读取
						in.skip(beginPoint);
						byte[] buffer = new byte[1024];
						int count;
						// 定义当前下载进度
						int process = beginPoint;
						// 当前进度必须小于结束字节数
						while (process < endPoint) {

							count = in.read(buffer);
							// 判断是否读到最后一块
							if (process + count >= endPoint) {
								count = endPoint - process;
								process = endPoint;
							} else {
								// 计算当前进度
								process += count;
							}
							// 保存文件流
							fos.write(buffer, 0, count);

						}
						fos.close();
						in.close();

					} catch (Exception e) {
						e.printStackTrace();
					}
				}

			};
			threads[i].start();

		}

		// 当所有线程都结束时才开始文件的合并
		for (Thread t : threads) {
			t.join();
		}

		// 若该文件夹不存在,则创建一个文件夹
		File filePath = new File("E:/download/");
		if (!filePath.exists()) {
			filePath.mkdirs();
		}
		// 定义文件输出流
		FileOutputStream fos = new FileOutputStream("E:/download/" + fileName);
		for (int i = 0; i < blockNum; i++) {
			FileInputStream fis = new FileInputStream("E:/temp_file/" + fileName + "_" + (i + 1));
			byte[] buffer = new byte[1024];
			int count;
			while ((count = fis.read(buffer)) > 0) {
				fos.write(buffer, 0, count);
			}
			fis.close();
		}
		fos.close();

		long end_time = new Date().getTime();
		long seconds = (end_time - begin_time) / 1000;
		long minutes = seconds / 60;
		long second = seconds % 60;

		System.out.println("下载完成,用时:" + minutes + "分" + second + "秒");

	}

}

 

该类利用了多线程进行文件的下载,等到每个线程都下载完成后,我们将每个线程下载好的文件合并为一个完整的文件。

可以看到,三个线程同时进行下载,下图展示了临时文件的存储情况:

程序成功运行完后,控制台输出情况如下:

当所有的线程都下载好了临时文件后,程序会将这些临时文件合并为一个完整的文件:

这个时候,我们可以看到一个完整的文件已经下载到了我们指定的文件夹中了,这样,我们利用URL进行多线程下载就成功了。

该文章只是作为我学习URL和多线程的笔记,刚入门的童鞋可以参考一下,如有错误,欢迎指正。

文章属原创,如需引用,请注明出处,谢谢。

  • 14
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值