iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >java实现高效下载文件的方法
  • 444
分享到

java实现高效下载文件的方法

2024-04-02 19:04:59 444人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

本文实例为大家分享了java实现下载文件的方法,供大家参考,具体内容如下 本文我们介绍几种方法下载文件。从基本JAVA io 到 NIO包,也介绍第三方库的一些方法,如Async H

本文实例为大家分享了java实现下载文件的方法,供大家参考,具体内容如下

本文我们介绍几种方法下载文件。从基本JAVA ioNIO包,也介绍第三方库的一些方法,如Async Http Client 和 Apache Commons IO.
最后我们还讨论在连接断开后如何恢复下载。

使用java IO

下载文件最基本的方法是java IO,使用URL类打开待下载文件的连接。为有效读取文件,我们使用openStream() 方法获取 InputStream:


BufferedInputStream in = new BufferedInputStream(new URL(FILE_URL).openStream())

当从InputStream读取文件时,强烈建议使用BufferedInputStream去包装InputStream,用于提升性能。
使用缓存可以提升性能。read方法每次读一个字节,每次方法调用意味着系统调用底层的文件系统。当JVM调用read()方法时,程序执行上下文将从用户模式切换到内核模式并返回。

从性能的角度来看,这种上下文切换非常昂贵。当我们读取大量字节时,由于涉及大量上下文切换,应用程序性能将会很差。

为了读取URL的字节并写至本地文件,需要使用FileOutputStream 类的write方法:


try (BufferedInputStream in = new BufferedInputStream(new URL(FILE_URL).openStream());
  FileOutputStream fileOutputStream = new FileOutputStream(FILE_NAME)) {
    byte dataBuffer[] = new byte[1024];
    int bytesRead;
    while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
        fileOutputStream.write(dataBuffer, 0, bytesRead);
    }
} catch (IOException e) {
    // handle exception
}

使用BufferedInputStream,read方法按照我们设置缓冲器大小读取文件。示例中我们设置一次读取1024字节,所以BufferedInputStream 是必要的。

上述示例代码冗长,幸运的是在Java7中Files类包含处理IO操作的助手方法。可以使用File.copy()方法从InputStream中读取所有字节,然后复制至本地文件:


InputStream in = new URL(FILE_URL).openStream();
Files.copy(in, Paths.get(FILE_NAME), StandardCopyOption.REPLACE_EXISTING);

上述代码可以正常工作,但缺点是字节被缓冲到内存中。Java为我们提供了NIO包,它有方法在两个通道之间直接传输字节,而无需缓冲。下面我们会详细讲解。

使用NIO

java NIO包提供了无缓冲情况下在两个通道之间直接传输字节的可能。

为了读来自URL的文件,需从URL流创建ReadableByteChannel :


ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream());

从ReadableByteChannel 读取字节将被传输至FileChannel:


FileOutputStream fileOutputStream = new FileOutputStream(FILE_NAME);
FileChannel fileChannel = fileOutputStream.getChannel();

然后使用transferFrom方法,从ReadableByteChannel 类下载来自URL的字节传输到FileChannel:


fileOutputStream.getChannel()
  .transferFrom(readableByteChannel, 0, Long.MAX_VALUE);

transferTo() 和 transferFrom() 方法比简单使用缓存从流中读更有效。依据不同的底层操作系统,数据可以直接从文件系统缓存传输到我们的文件,而不必将任何字节复制到应用程序内存中。

linux和UNIX系统上,这些方法使用零拷贝技术,减少了内核模式和用户模式之间的上下文切换次数。

使用第三方库

上面我们已经使用java 核心功能实现从URL下载文件。当无需调整性能是,我们也可以利用第三方库轻松实现。举例,在实际场景中,需要实现异步下载,我们可以封装逻辑至Callable,下面看已有库实现。

Async HTTP Client

Async HTTP Client是使用Netty框架执行异步HTTP请求的流行库。我们使用它对URL文件执行GET请求并获取其内容。首先需要创建HTTP client:


AsyncHttpClient client = Dsl.asyncHttpClient();

下面内容放到FileOutputStream:


FileOutputStream stream = new FileOutputStream(FILE_NAME);

接下来,创建HTTP GET请求并注册AsyncCompletionHandler 处理器去处理下载内容:


client.prepareGet(FILE_URL).execute(new AsyncCompletionHandler<FileOutputStream>() {

    @Override
    public State onBodyPartReceived(HttpResponseBodyPart bodyPart) 
      throws Exception {
        stream.getChannel().write(bodyPart.getBodyByteBuffer());
        return State.CONTINUE;
    }

    @Override
    public FileOutputStream onCompleted(Response response) 
      throws Exception {
        return stream;
    }
})

上面我们覆盖了onBodyPartReceived() 方法。缺省实现是累加HTTP 接收块至ArrayList,这可能导致耗费高内存或下载大文件时OutOfMemory 异常。

代替累加每个HttpResponseBodyPart 至内存,我们使用FileChannel写字节至本地文件。getBodyByteBuffer()方法通过ByteBuffer访问bodyPart内容。ByteBuffers的优势是把内存分配到JVM堆之外,所以不会影响应用程序的内存。

Apache Commons IO

另一个高可用的IO操作库是Apache Commons IO。我们从其Javadoc看到FileUtils实用类,用于一般的文件操作任务。从URL下载文件,仅需一行代码:


FileUtils.copyURLToFile(
  new URL(FILE_URL), 
  new File(FILE_NAME), 
  CONNECT_TIMEOUT, 
  READ_TIMEOUT);

从性能角度看,与前面JAVA IO示例相同。底层代码使用相同的概念,从InputStream读取一些字节并将它们写入OutputStream。不同之处在于,URLConnection类在这里用于控制连接超时,这样下载就不会阻塞很长时间:


URLConnection connection = source.openConnection();
connection.setConnectTimeout(connectionTimeout);
connection.setReadTimeout(readTimeout);

恢复下载

考虑到internet连接的不确定性,失败时我们可以重新下载文件,但不是再次从字节0位置下载文件。
让我们重写前面的第一个示例,以添加这个功能。

我们首先要知道的是,我们可以使用HTTP HEAD方法从给定URL读取文件的大小,而无需实际下载它:


URL url = new URL(FILE_URL);
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestMethod("HEAD");
long removeFileSize = httpConnection.getContentLengthLong();

现在我们有了文件内容的总大小,可以检查文件是否已下载了部分内容。如果是,我们将继续从磁盘上记录的最后一个字节开始下载:


long existingFileSize = outputFile.length();
if (existingFileSize < fileLength) {
    httpFileConnection.setRequestProperty(
      "Range", 
      "bytes=" + existingFileSize + "-" + fileLength
    );
}

上述代码我们配置了URLConnection以在一定范围内请求文件内容。范围将从最后下载的字节位置开始,并以远程文件大小的字节长度为结束。

使用范围HEAD标识的另一种常见方法是通过设置不同的字节范围以块形式下载文件。例如,要下载2KB文件,我们可以使用范围0 - 1024和1024 - 2048。

与前节代码稍微不同的是设置FileOutputStream 方法append参数为true:


OutputStream os = new FileOutputStream(FILE_NAME, true);

在我们做了这个更改之后,其余的代码与我们前面看到的代码一样。

总结

在本文中,我们已经看到Java中从URL下载文件的几种实现方式。

最常见的实现是在执行读/写操作时使用缓冲区。这个实现即使对于大文件也是安全的,因为我们没有将整个文件加载到内存中。

我们还了解了如何使用Java NIO通道实现零拷贝下载。这很有用,因为它最小化了在读取和写入字节时执行的上下文切换的次数,并且通过使用直接缓冲区字节不会加载到应用程序内存中。另外,由于下载文件通常是通过HTTP完成的,我们也说明如何使用AsyncHttpClient库实现这一点。

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

--结束END--

本文标题: java实现高效下载文件的方法

本文链接: https://www.lsjlt.com/news/133639.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • java实现高效下载文件的方法
    本文实例为大家分享了java实现下载文件的方法,供大家参考,具体内容如下 本文我们介绍几种方法下载文件。从基本JAVA IO 到 NIO包,也介绍第三方库的一些方法,如Async H...
    99+
    2024-04-02
  • java实现文件下载的两种方式
    本文实例为大家分享了java实现文件下载的具体代码,供大家参考,具体内容如下public HttpServletResponse download(String path, HttpServletResponse response) { ...
    99+
    2023-05-30
    java 文件下载 ava
  • Java实现文件上传和下载的方法详解
    目录1、文件上传1.1 介绍1.2 代码实现2、下载2.1 介绍2.2 代码实现1、文件上传 1.1 介绍 文件上传,也称为upload,是指将本地图片、视频、音频等文件上传到服务器...
    99+
    2024-04-02
  • Java实现下载文件的6种方式
    1. 使用URL类的openStream()方法下载文件:```javaURL url = new URL(fileUrl);Inp...
    99+
    2023-08-08
    Java
  • Golang多线程下载器实现高效快速地下载大文件
    目录前言请求资源http1.1协议Range\Content-RangeLast-Modified\If-Modified-SinceNewRequest()http.Default...
    99+
    2023-05-19
    Golang多线程下载器 Golang下载文件
  • java实现文件下载的方式有哪些
    在Java中,可以使用以下方式实现文件下载: 使用URL和URLConnection类:可以通过创建URL对象,然后打开连接并获取...
    99+
    2024-04-08
    java
  • java高并发文件上传下载怎么实现
    实现高并发的文件上传下载可以通过以下几个步骤: 使用多线程或线程池:可以使用多个线程或线程池来处理文件上传下载请求,每个线程负责...
    99+
    2023-10-27
    java
  • Java如何实现下载文件的几种方式
    目录 一、以流的方式下载二、下载本地文件三、下载网络文件四、在线打开的方式五、将文件转换成base64六、将MultipartFile转换为File 一、以流的方式下载 public ...
    99+
    2023-09-06
    java 开发语言
  • Java下载Excel模板文件的实现
    在项目中经常会用到文件下载的功能,比如下载excel模板,这里简单记录一下实现过程 将模板文件放到项目资源文件目录中,也可以自定义其他位置,只要通过路径能找到该文件就行:  2、controller层写下载的接口 @Ge...
    99+
    2023-08-31
    java servlet html
  • Java实现HDFS文件上传下载
    本文实例为大家分享了利用Java实现HDFS文件上传下载的具体代码,供大家参考,具体内容如下 1、pom.xml配置 <!--配置--> <properties&g...
    99+
    2024-04-02
  • java实现文件上传和下载
    本文实例为大家分享了java实现文件上传和下载的具体代码,供大家参考,具体内容如下 文件的上传 upload:文件上传 客户端通过表单的文件域file  把客户端的文件 上...
    99+
    2024-04-02
  • php实现文件下载功能的方法是什么
    本篇内容主要讲解“php实现文件下载功能的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“php实现文件下载功能的方法是什么”吧!一、实现文件下载的基本原理在PHP中,实现文件下载的原理...
    99+
    2023-07-06
  • 如何通过Java实现高效的文件重定向和加载?
    Java是一种流行的编程语言,用于开发各种应用程序。在Java应用程序中,文件重定向和加载是非常重要的任务。本文将介绍如何使用Java实现高效的文件重定向和加载,以便您可以更好地了解如何处理文件操作。 文件重定向 Java中的文件重定向是将...
    99+
    2023-09-05
    文件 重定向 load
  • java实现文件上传下载功能
    本文实例为大家分享了java实现文件上传下载的具体代码,供大家参考,具体内容如下 1.上传单个文件 Controller控制层 import java.io.File; imp...
    99+
    2024-04-02
  • Android实现文件下载
    前言 总体思路:下载文件到应用缓存路径,在相册创建文件夹,Copy过去,通知相册刷新。 下载文件到APP缓存路径,这样可避免Android高版本读取本地权限问题, 准备 impl...
    99+
    2024-04-02
  • ASP.NETMVC实现文件下载
    思路 点击一个链接,把该文件的Id传递给控制器方法,遍历文件夹所有文件,根据ID找到对应文件,并返回FileResult类型。 与文件相关的Model: namespace MvcA...
    99+
    2022-11-13
    ASP.NET MVC 文件下载
  • thinkphp5实现文件下载
    public function download() { $famlePath = $_GET[‘resum’]; f i ...
    99+
    2023-09-01
    php
  • 如何在PHP编程中实现高效的文件加载算法?
    PHP是一种广泛使用的编程语言,其灵活性和易用性使其成为许多Web应用程序的首选语言。然而,PHP的一个普遍问题是文件加载速度慢,特别是当应用程序包含大量的文件时。在这篇文章中,我们将讨论如何在PHP编程中实现高效的文件加载算法,以提高应用...
    99+
    2023-08-07
    编程算法 文件 load
  • Java 实现浏览器下载文件及文件预览
    插曲想记录一下,以后可以来粘贴复制用。 一、浏览器下载文件 setContentType() 该实体头的作用是让服务器告诉浏览器它发送的数据属于什么文件类型。 没有缓存 resp...
    99+
    2024-04-02
  • php怎么实现下载时修改文件名的方法
    本文将为大家详细介绍“php怎么实现下载时修改文件名的方法”,内容步骤清晰详细,细节处理妥当,而小编每天都会更新不同的知识点,希望这篇“php怎么实现下载时修改文件名的方法”能够给你意想不到的收获,请大家跟着小编的思路慢慢深入,具体内容如下...
    99+
    2023-06-06
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作