使用Java高效率解决远程文件下载解决方案

项目发布,需要把老版数据文件迁移到新的服务器中,由于老版服务器中存在很多垃圾文件并且数量较大,全部迁移过去不太现实,所以就需要根据文件的地址将有用的文件下载下来再放到新版服务器中。原本想使用迅雷下载,但是那么多的文件效率太低了。所以突发奇想,自己写一个下载程序得了。总共写了三版。

第一版

//------------------------------------------第一版----------------------------------------------------/*** @Author FHL* @Description: 方法1* @Date: 2020/8/1 14:48* @Param: []* @return: void*/@Testpublic void fileDownload() {long startTime = System.currentTimeMillis();//远程地址(数据库中是不存在全路径的,这里下载的时候是需要前缀拼上数据库半路径后缀)String prefixUrl = "网络下载地址前缀";//本地路径String localPath = "本地地址";//查询数据库将下载地址放入listList<CpicDdzsActivityDO> urlList = cpicDdzsActivityDao.fileDown();int i = 0;for (CpicDdzsActivityDO cdad : urlList) {//数据库半路径后缀String suffixUrl = cdad.getFilePath();//地址为空或外链直接跳出if (suffixUrl==null || "".equals(suffixUrl) || suffixUrl.startsWith("http")){continue;}try {//全路径(下载地址拼接)URL root = new URL(prefixUrl + suffixUrl);Integer integer = saveBinary(root, suffixUrl, localPath);if (integer==-1){logger.info("第"+(++i)+"个文件:"+suffixUrl + "-->文件长度小于0");continue;}} catch (MalformedURLException e) {logger.info(suffixUrl + "is not URL");} catch (IOException e) {logger.info("错误--> "+e.getMessage());}logger.info("第"+(++i)+"个文件");}long endTime = System.currentTimeMillis();logger.info("共用时:"+(endTime-startTime));}/*** @Author FHL* @Description:* @Date: 2020/7/30 15:13* @Param: []* @return: void*/public Integer saveBinary(URL u, String suffixUrl, String localPath) throws IOException {HttpURLConnection uc = (HttpURLConnection)u.openConnection();String contentType = uc.getContentType();//设置超时间为3秒uc.setConnectTimeout(3*1000);//防止屏蔽程序抓取而返回403错误uc.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");//得到输入流InputStream inputStream = uc.getInputStream();try (InputStream raw = uc.getInputStream()) {InputStream in = new BufferedInputStream(raw);byte[] data = new byte[1024];int offset = 0;ByteArrayOutputStream bos = new ByteArrayOutputStream();while ((offset = in.read(data)) != -1) {bos.write(data, 0, offset);}bos.close();//获取自己数组byte[] getData = bos.toByteArray();//创建文件夹String filename = localPath+suffixUrl;File saveDir = new File(filename);if (!saveDir.getParentFile().exists()){saveDir.getParentFile().mkdirs();}//File file = new File(filename);FileOutputStream fos = new FileOutputStream(saveDir);fos.write(getData);if(fos!=null){fos.close();}if(inputStream!=null){inputStream.close();}}return 1;}

第一版是采用原生的HttpURLConnection进行下载的,问题比较大,当时有些文件是下载不下来。
遗留问题:
某些文件无法下载,我怀疑的原因:
1、可能是文件的文件的返回的responseCode不是200的原因,如果responseCode不是200你却还用HttpURLConnection .getInputStream()方法来解析的话是有问题的,你需要使用HttpURLConnection .getErrorStream()方法来解析。这个原因还是我写这篇文章的时候突然想到这个原因的,因为之前我写过一个微信文章解析的一个功能就遇到类似的问题
当时是这样写的:

int responseCode = connection.getResponseCode();
logger.info("responseCode>>>>>>>>>>>>>>>>>>>>>>>>>>" + responseCode);
BufferedReader br = null;
if (responseCode == HttpURLConnection.HTTP_OK) {br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
} else if (responseCode > 200) {br = new BufferedReader(new InputStreamReader(connection.getErrorStream(), "utf-8"));
}

2、
缺陷:
1、存在问题,某些文件无法下载(可以解决)
2、效率低
3、代码不健全、臃肿

第二版

 //用来统计线程是否执行完毕 如果countDownLatch为0代表全部执行完毕了private CountDownLatch countDownLatch = null;private CountDownLatch countDownLatch2 = null;private ReentrantReadWriteLock readLock = new ReentrantReadWriteLock();//------------------------------------------第二版----------------------------------------------------/*** @Author FHL* @Description: 方法2* @Date: 2020/8/1 14:48* @Param: [args]* @return: void*/@Testpublic void fileDownload2() {long startTime = System.currentTimeMillis();//远程地址(数据库中是不存在全路径的,这里下载的时候是需要前缀拼上数据库半路径后缀)String prefixUrl = "网络下载地址前缀";//本地地址String localPath = "本地地址";//查询数据库将下载地址放入listList<CpicDdzsActivityDO> urlList = cpicDdzsActivityDao.fileDown();int i = 0;for (CpicDdzsActivityDO cdad : urlList) {//远程地址String suffixUrl = cdad.getFilePath();//地址为空或外链直接跳出if (suffixUrl==null || "".equals(suffixUrl) || suffixUrl.startsWith("http")){continue;}try{Integer integer = downLoadFromUrl(prefixUrl, suffixUrl, localPath);if (integer==1){logger.info("第"+(++i)+"个文件");}}catch (MalformedURLException e) {logger.info("第"+(++i)+"个文件不存在--> "+suffixUrl);}catch (IOException e) {logger.info("第"+(++i)+"个文件错误--> "+suffixUrl+":"+e.getMessage());}}long endTime = System.currentTimeMillis();logger.info("共用时:"+(endTime-startTime));}/*** @Author FHL* @Description: 从网络Url中下载文件* @Date: 2020/8/1 15:47* @Param: [prefixUrl, suffixUrl, localPath]* @return: void*/public Integer downLoadFromUrl(String prefixUrl, String suffixUrl,String localPath) throws IOException{URL url = new URL(prefixUrl+suffixUrl);HttpURLConnection conn = (HttpURLConnection)url.openConnection();//设置超时间为3秒conn.setConnectTimeout(3*1000);//防止屏蔽程序抓取而返回403错误conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");//得到输入流InputStream inputStream = conn.getInputStream();//获取自己数组byte[] getData = readInputStream(inputStream);//文件保存位置File saveDir = new File(localPath+suffixUrl);if(!saveDir.getParentFile().exists()){saveDir.getParentFile().mkdirs();}//File file = new File(localPath+suffixUrl);FileOutputStream fos = new FileOutputStream(saveDir);fos.write(getData);if(fos!=null){fos.close();}if(inputStream!=null){inputStream.close();}cpicDdzsActivityDao.updateFileDownStatus(id);return 1;}/*** 从输入流中获取字节数组* @param inputStream* @return* @throws IOException*/public  byte[] readInputStream(InputStream inputStream) throws IOException {byte[] buffer = new byte[1024];int len = 0;ByteArrayOutputStream bos = new ByteArrayOutputStream();while((len = inputStream.read(buffer)) != -1) {bos.write(buffer, 0, len);}bos.close();return bos.toByteArray();}

和第一版相比我只是稍作封装,差别并不大,但是第一版的问题为什么不能下载,暂时我也没有头绪,自己太菜了。
优点:修复第一版的某些文件不能下载的问题,任何文件都可以下载
缺陷:文件量过大,效率不高

第三版

 //用来统计线程是否执行完毕 如果countDownLatch为0代表全部执行完毕了private CountDownLatch countDownLatch = null;private CountDownLatch countDownLatch2 = null;private ReentrantReadWriteLock readLock = new ReentrantReadWriteLock();//------------------------------------------第三版----------------------------------------------------/*** @Author FHL* @Description: 方法3(任何文件都可以下载,大量文件效率高)* @Date: 2020/8/11 11:06* @Param: []* @return: void*/@Testpublic void fileDownload3() {long startTime = System.currentTimeMillis();List<CpicDdzsActivityDO> urlList = cpicDdzsActivityDao.fileDown();try {createTenThreadReadList(urlList, 10);} catch (Exception e) {e.printStackTrace();}long endTime = System.currentTimeMillis();logger.info("共用时:"+(endTime-startTime));}/*** @Author FHL* @Description: 使用多线程下载文件* @Date: 2020/8/11 11:11* @Param: [list, threadNum]* @return: void*/private void createTenThreadReadList(List<CpicDdzsActivityDO> list, Integer threadNum) throws Exception{ExecutorService readListExecutors = Executors.newFixedThreadPool(threadNum);Integer pageSize = list.size() % threadNum == 0 ? list.size() / threadNum : (list.size() / threadNum + 1);countDownLatch2 = new CountDownLatch(threadNum);ReentrantReadWriteLock readWriteLockLock = new ReentrantReadWriteLock();for (int i = 0; i < threadNum; i++) {//数据分段读取添加listint end = pageSize * (i + 1);int startSize = i * pageSize;int forCountSize = end > list.size() ? list.size() : end;logger.info("start=" + startSize + "     forSize=" + forCountSize);readListExecutors.execute(new Runnable() {@Overridepublic void run() {try {//使用读锁readWriteLockLock.readLock().lock();logger.info("线程" + Thread.currentThread().getName() + "在读取list操作");List<CpicDdzsActivityDO> listThread = new ArrayList<>();for (int j = startSize; j < forCountSize; j++) {listThread.add(list.get(j));}fileDownloadThread(listThread);countDownLatch2.countDown();} finally {readWriteLockLock.readLock().unlock();}}});}readListExecutors.shutdown();while(true){if(readListExecutors.isTerminated()){logger.info("所有的子线程都结束了!");break;}Thread.sleep(200);}}public void fileDownloadThread(List<CpicDdzsActivityDO> urlList){//远程地址(数据库中是不存在全路径的,这里下载的时候是需要前缀拼上数据库半路径后缀)String prefixUrl = "网络下载地址前缀";//本地地址String localPath = "本地地址";int i = 0;for (CpicDdzsActivityDO cdad : urlList) {//远程地址String suffixUrl = cdad.getFilePath();//地址为空或外链直接跳出if (suffixUrl==null || "".equals(suffixUrl) || suffixUrl.startsWith("http")){continue;}try{Integer integer = downLoadFromUrl(prefixUrl, suffixUrl, localPath);if (integer==1){logger.info("第"+(++i)+"个文件");}}catch (MalformedURLException e) {logger.info("第"+(++i)+"个文件不存在--> "+suffixUrl);}catch (IOException e) {logger.info("第"+(++i)+"个文件错误--> "+suffixUrl+":"+e.getMessage());}}}/*** @Author FHL* @Description: 从网络Url中下载文件* @Date: 2020/8/1 15:47* @Param: [prefixUrl, suffixUrl, localPath]* @return: void*/
public Integer downLoadFromUrl(String prefixUrl, String suffixUrl,String localPath) throws IOException{URL url = new URL(prefixUrl+suffixUrl);HttpURLConnection conn = (HttpURLConnection)url.openConnection();//设置超时间为3秒conn.setConnectTimeout(3*1000);//防止屏蔽程序抓取而返回403错误conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");//得到输入流InputStream inputStream = conn.getInputStream();//获取自己数组byte[] getData = readInputStream(inputStream);//文件保存位置File saveDir = new File(localPath+suffixUrl);if(!saveDir.getParentFile().exists()){saveDir.getParentFile().mkdirs();}//File file = new File(localPath+suffixUrl);FileOutputStream fos = new FileOutputStream(saveDir);fos.write(getData);if(fos!=null){fos.close();}if(inputStream!=null){inputStream.close();}return 1;
}/*** 从输入流中获取字节数组* @param inputStream* @return* @throws IOException*/public byte[] readInputStream(InputStream inputStream) throws IOException {byte[] buffer = new byte[1024];int len = 0;ByteArrayOutputStream bos = new ByteArrayOutputStream();while((len = inputStream.read(buffer)) != -1) {bos.write(buffer, 0, len);}bos.close();return bos.toByteArray();}

优点:使用多线程下载文件,效率显著提高。本机或服务器配置好的话,可以提高线程数量;本机的话10个线程差不多就可以了。

第一版的出现的问题,我会继续找的,我也希望大家帮我看看问题到底在哪[抱拳][抱拳]

使用Java解决远程文件下载解决方案相关推荐

  1. java实现远程文件下载

    转自JAVA 实现远程文件下载 相信很多同学在实际的项目开发中都会遇到一个问题,如何跨服务下载文件?在传统SSH, SSH2, SSM架构中可能很少遇到这样的问题,但是在当前逐渐流行的微服务架构中,这 ...

  2. JAVA 实现远程文件下载

    相信很多同学在实际的项目开发中都会遇到一个问题,如何跨服务下载文件?在传统SSH,SSH2,SSM架构中可能很少遇到这样的问题,但是在当前逐渐流行的微服务架构中,这是一个很常见的问题. 举个例子,比如 ...

  3. java远程文件下载到本地

    java远程文件下载到本地 适用场景:我们再登录网站后选择播放音频,如果需要将音频或者视频下载到本地时,而网站资源又进行了加密,无法获得的情况下.使用该工具类模拟浏览器访问下载 package com ...

  4. Java中文乱码特殊字符解决方案

    Java中文乱码&特殊字符解决方案 相信很多朋友遇到过Java的乱码问题,最近我也在解决一个"使用文本生成图片过程中中文以及特殊字符乱码"的问题:花了我大量时间,Debug ...

  5. Linux内存耗尽宕机6,转载:Linux服务器Cache占用过多内存导致系统内存不足最终java应用程序崩溃解决方案...

    原文链接: https://blog.csdn.net/u014740338/article/details/66975550 问题描述 Linux内存使用量超过阈值,使得Java应用程序无可用内存, ...

  6. java 下载加速_一种基于Java的大文件下载加速方法与流程

    本发明涉及java/多线程技术领域,涉及一种加速文件下载装置,具体提供一种基于java的大文件下载加速方法. 背景技术: 现有的常用下载方式是基于浏览器的单线程下载.这种单线程下载的方式,是通过htt ...

  7. springmvc web网站开发上传视频到远程服务器解决方案

    springmvc web网站开发上传视频到远程服务器解决方案!近期在给学校做官方网站设计时,有一个业务需求是,后台要增加一个视频管理模块,管理员在后台可以把本地硬盘剪辑好的视频文件,上传到远程服务器 ...

  8. java显示一张图片不显示_微信图片不可显示java解决方法

    场景: 微信上传了图片素材,返回了图片url,然后不能在img标签中正常显示. 原因是微信做了图片防盗连接. 解决方法: 原理:使用你的服务端脚本,远程抓取图片,然后输出image/* 格式,就可以了 ...

  9. Java路径问题最终解决方案

    http://blog.csdn.net/shendl/article/details/1427475  Java路径问题最终解决方案 -可定位所有资源的相对路径寻址 前言 Java的路径问题,非常难 ...

最新文章

  1. 编写程序,输入某年某月,求该月有多少天
  2. AI学会了用“人眼”看世界,甚至连人类瞳孔的细微缩放都能模拟 | 杜克大学...
  3. android evaluater_android通过WebView的evaluateJavascript()调用JS
  4. 经纬度坐标系与UTM MGRS坐标系之间的转换 c# 版本
  5. python企业级框架_Python六大开源框架对比:Web2py略胜一筹
  6. SAP Enterprise search test report ESH_TEST_SEARCH debug in Q2D
  7. linux vi删除操作,vi删除操作
  8. python全栈-Day 1
  9. php显示动态通告信息方式,Joomla PHP通知,警告和错误指南
  10. malloc动态内存分配
  11. 05-UIDynamic
  12. Android中Service的一个Demo例子
  13. HttpRequest 和HttpWebRequest的区别
  14. 百度编辑器ueditor获取不到内容?请把form放在table等其他元素最外面
  15. 《Windows程序设计》复习题
  16. C语言——函数的调用
  17. MATLAB 2018a安装
  18. swf文件的反编译入门
  19. Assembler--Error: invalid instruction suffix for `push‘
  20. 图解MySQL系列(2)-SQL实战研究InnoDB架构设计

热门文章

  1. 【Java基础】Linux系统
  2. 简单!三步实现微信消息同步!!
  3. 解决联想拯救者混合模式+不插电情况下屏幕亮度和颜色异常问题
  4. An Introduction to K-theory
  5. 大学选人工智能专业好不好?
  6. qt之TCP/IP通信客户端与服务器自动连接互相传输数据
  7. 关于navicat连接oracle错误:ora-123737:instant client light:unsupported server character set zhs16gbk...
  8. “中国十大名校”之争,缘何让百度气急败坏删帖?
  9. 特征融合 Pytorch concat串连两个预训练特征
  10. html安装网卡驱动,网卡驱动,详细教您网卡驱动怎么安装