Java使用NIO优化IO实现文件上传下载功能

目录
  • 1 NIO的一些基础预备知识
  • 2 NIO为何较传统的io速度较快
  • 3 NIO实战上传下载
    • 3.1 url下载文件
    • 3.2 通过NIO上传文件

1 NIO的一些基础预备知识

Java中IO流类的体系中BIO与NIO:https://blog.csdn.net/ZGL_cyy/article/details/104326458
Java IO体系与NIO和BIO体系面试题 :https://blog.csdn.net/ZGL_cyy/article/details/122836368
为什么使用NIO:因为传统IO文件传输速率低,所以选择了NIO进行文件的下载操作。NIO还有一个好处就是其中零拷贝可以实现减少内存中数据的重复,减少CPU操作的效果。所以相对于传统IO,NIO有着效率高点的优势。

2 NIO为何较传统的io速度较快

就拿单个io过程来看,首先时间主要花在了用户态和内核态的转换上,其次,考虑将多个io的“合并”为一个io,这不就节省时间了吗

相应的NIO主要做了两方面的提升

1.避免了用户态和内核态的交换,直接操作内存,用户态和内核态的转换是很费时的,传统的io写入磁盘时,用户态的接口不能直接操作内存,而是通过操作系统调用内核态接口来进行io。

2.利用buffer减少io的次数,buffer化零为整”的写入方式因为大大减小了寻址/写入次数,所以就降低了硬盘的负荷。

3.IO 是基于流来读取的,而NIO则是基于块读取,面向流 的 I/O 系统一次一个字节地处理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。为流式数据创建过滤器非常容易。链接几个过滤器,以便每个过滤器只负责单个复杂处理机制的一部分,这样也是相对简单的。不利的一面是,面向流的 I/O 通常相当慢。
一个 面向块 的 I/O 系统以块的形式处理数据。每一个操作都在一步中产生或者消费一个数据块。按块处理数据比按(流式的)字节处理数据要快得多。但是面向块的 I/O 缺少一些面向流的 I/O 所具有的优雅性和简单性。

4.非阻塞IO 和 异步IO的支持, 减少线程占有的栈空间,以及上下文切换

5.IO 多路复用的支持

6.Buffer 支持,所有读写操作都是基于 缓冲 来实现

7.NIO 支持 Direct Memory, 可以减少一次数据拷贝

8.Netty 零拷贝的支持

3 NIO实战上传下载

3.1 url下载文件

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系统上,这些方法使用零拷贝技术,减少了内核模式和用户模式之间的上下文切换次数。

工具类:

/**NIO文件下载工具类
 * @author olalu
 */
public class NioDownloadUtils {

    /**
     * @description:
     * @param file: 要下在文件
     * @return: void
     */
    public static void downloadDoc(File file,HttpServletResponse response) throws IOException {
        OutputStream outputStream = response.getOutputStream();
        String contentType = Files.probeContentType(Paths.get(file.getAbsolutePath()));
        //设置响应头
        response.setHeader("Content-Type", contentType);
        response.setHeader("Content-Disposition", "attachment;filename="+ new String(file.getName().getBytes("utf-8"),"ISO8859-1"));
        response.setContentLength((int) file.length());
        //获取文件输入流
        FileInputStream fileInputStream = new FileInputStream(file);
        //获取输出流通道
        WritableByteChannel writableByteChannel = Channels.newChannel(outputStream);
        FileChannel fileChannel = fileInputStream.getChannel();
        //采用零拷贝的方式实现文件的下载
        fileChannel.transferTo(0,fileChannel.size(),writableByteChannel);
        //关闭对应的资源
        fileChannel.close();
        outputStream.flush();
        writableByteChannel.close();
    }

    public static void downloadDoc(String path,HttpServletResponse response) throws IOException {
        File file = new File(path);
        if (!file.exists()){
            throw new RuntimeException("文件不存在");
        }
        downloadDoc(file,response);
    }

}

3.2 通过NIO上传文件

/**
     * 文件上传方法
     */
    public static Result uploading(MultipartFile file) {
        //获取文件名
        String realName = file.getOriginalFilename();
        String newName = null;
        if(realName != null && realName != ""){
            //获取文件后缀
            String suffixName = realName.substring(realName.lastIndexOf("."));
            //生成新名字
            newName = UUID.randomUUID().toString().replaceAll("-", "")+suffixName;
        }else {
            return Result.fail("文件名不可为空");
        }
        //创建流
        FileInputStream fis = null;
        FileOutputStream fos = null;
        //创建通道
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            fis = (FileInputStream)file.getInputStream();
            //开始上传
            fos = new FileOutputStream(UPLOAD_URL+"\\"+newName);
            //通道间传输
            inChannel = fis.getChannel();
            outChannel = fos.getChannel();
            //上传
            inChannel.transferTo(0,inChannel.size(),outChannel);

        }catch (IOException e){
            return Result.fail("文件上传路径错误");
        }finally {
            //关闭资源
            try {
                if (fis != null) {
                    fis.close();
                }
                if (fos != null) {
                    fos.close();
                }
                if (inChannel != null) {
                    inChannel.close();
                }
                if (outChannel != null) {
                    outChannel.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return Result.ok(newName);

    }

到此这篇关于Java使用NIO优化IO实现文件上传下载的文章就介绍到这了,更多相关Java NIO文件上传下载内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java实现文件上传和下载

    本文实例为大家分享了java实现文件上传和下载的具体代码,供大家参考,具体内容如下 文件的上传 upload:文件上传 客户端通过表单的文件域file  把客户端的文件 上传保存到服务器的硬盘上 页面 首先对上传的表单有以下要求: 必须有文件域:input type=file 表单提交方式:method=post 表单的 enctype=multipart/form-data <form method="post" action="/user/regist"

  • java基于Apache FTP实现文件上传、下载、修改文件名、删除

    Apache FTP 是应用比较广泛的FTP上传客户端工具,它易于操作,代码简略,结构清晰,是做FTP文件客户端管理软件的优先之选.FTP的操作包括:FTP文件上传(断点续传).FTP文件下载.FTP文件重命名.FTP文件删除,这些操作已经将FTP应用管理的方式发挥的淋漓尽致了,So 我一直都用此种方式来实现FTP文件服务器的管理工作:下附FTP工具代码. 1.FTP文件操作状态枚举类 package com.scengine.wtms.utils.ftp; public enum FTPSta

  • java实现文件上传下载和图片压缩代码示例

    分享一个在项目中用的到文件上传下载和对图片的压缩,直接从项目中扒出来的:) 复制代码 代码如下: package com.eabax.plugin.yundada.utils; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.

  • java实现文件上传下载功能

    本文实例为大家分享了java实现文件上传下载的具体代码,供大家参考,具体内容如下 1.上传单个文件 Controller控制层 import java.io.File; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapp

  • JavaWeb文件上传下载功能示例解析

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 1. 上传简单示例 Jsp <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"&g

  • JavaWeb文件上传与下载功能解析

    在开发过程中文件的上传下载很常用.这里简单的总结一下: 1.文件上传必须满足的条件: a. 页面表单的method必须是post 因为get传送的数据太小了 b. 页面表单的enctype必须是multipart/form-data类型的 c. 表单中提供上传输入域 代码细节: 客户端表单中:<form enctype="multipart/form-data"/> (如果没有这个属性,则服务端读取的文件路径会因为浏览器的不同而不同) 服务端ServletInputStre

  • java文件上传下载功能实现代码

    本文实例为大家分享了文件上传下载java实现代码,供大家参考,具体内容如下 前台: 1. 提交方式:post 2. 表单中有文件上传的表单项: <input type="file" /> 3. 指定表单类型:     默认类型:enctype="application/x-www-form-urlencoded"     文件上传类型:multipart/form-data FileUpload 文件上传功能开发中比较常用,apache也提供了文件上传组

  • Java使用NIO优化IO实现文件上传下载功能

    目录 1 NIO的一些基础预备知识 2 NIO为何较传统的io速度较快 3 NIO实战上传下载 3.1 url下载文件 3.2 通过NIO上传文件 1 NIO的一些基础预备知识 Java中IO流类的体系中BIO与NIO:https://blog.csdn.net/ZGL_cyy/article/details/104326458Java IO体系与NIO和BIO体系面试题 :https://blog.csdn.net/ZGL_cyy/article/details/122836368为什么使用N

  • java中struts2实现文件上传下载功能实例解析

    本文实例讲述了java中struts2实现文件上传下载功能实现方法.分享给大家供大家参考.具体分析如下: 1.文件上传 首先是jsp页面的代码 在jsp页面中定义一个上传标签 复制代码 代码如下: <tr>      <td align="right" bgcolor="#F5F8F9"><b>附件:</b></td>      <td bgcolor="#FFFFFF">

  • FasfDFS整合Java实现文件上传下载功能实例详解

    在上篇文章给大家介绍了FastDFS安装和配置整合Nginx-1.13.3的方法,大家可以点击查看下. 今天使用Java代码实现文件的上传和下载.对此作者提供了Java API支持,下载fastdfs-client-java将源码添加到项目中.或者在Maven项目pom.xml文件中添加依赖 <dependency> <groupId>org.csource</groupId> <artifactId>fastdfs-client-java</arti

  • 基于Java文件输入输出流实现文件上传下载功能

    本文为大家分享了Java实现文件上传下载功能的具体代码,供大家参考,具体内容如下 前端通过form表单的enctype属性,将数据传递方式修改为二进制"流"的形式,服务端(servlet)通过  getInputStream() 获取流信息, 运用java I/O 流的基础操作将流写入到一个服务端临时创建的文件temp中,然后再次利用文件基本操作,读取并截取临时文件内容,根据其中信息创建相应的文件,将读取出来的具体信息写入,下载时,根据提交的文件名称,找到服务器端相应的文件,然后根据输

  • Spring Boot + thymeleaf 实现文件上传下载功能

    最近同事问我有没有有关于技术的电子书,我打开电脑上的小书库,但是邮件发给他太大了,公司又禁止用文件夹共享,于是花半天时间写了个小的文件上传程序,部署在自己的Linux机器上. 提供功能: 1 .文件上传 2.文件列表展示以及下载 原有的上传那块很丑,写了点js代码优化了下,最后界面显示如下图: 先给出成果,下面就一步步演示怎么实现. 1.新建项目 首先当然是新建一个spring-boot工程,你可以选择在网站初始化一个项目或者使用IDE的Spring Initialier功能,都可以新建一个项目

  • c# 实现文件上传下载功能的实例代码

    NuGet 安装SqlSugar 1.Model文件下新建 DbContext 类 public class DbContext { public DbContext() { Db = new SqlSugarClient(new ConnectionConfig() { ConnectionString = "server=localhost;uid=root;pwd=woshishui;database=test", DbType = DbType.MySql, InitKeyTy

  • SpringMVC实现文件上传下载功能

    目录 导入需要的依赖包 一.单个文件上传 二.多个文件上传 三.上传文件列表显示 四.文件下载 今天遇到文件上传的问题,使用Ajax方式进行提交,服务器一直报错The current request is not a multipart request,看了网上很多方法,最后才找到,我在表单提交的时候使用了序列化$('#postForm').serialize(),但是这种方式,只能传递一般的参数,上传文件的文件流是无法被序列化并传递的.所以一直在报错.后来就直接使用submint(),放弃使用

  • SpringBoot实现文件上传下载功能小结

    最近做的一个项目涉及到文件上传与下载.前端上传采用百度webUploader插件.有关该插件的使用方法还在研究中,日后整理再记录.本文主要介绍SpringBoot后台对文件上传与下载的处理. 单文件上传 // 单文件上传 @RequestMapping(value = "/upload") @ResponseBody public String upload(@RequestParam("file") MultipartFile file) { try { if (

  • Struts2 控制文件上传下载功能实例代码

    之前介绍servlet3.0新特性的时候有提到过servlet API提供了一个part类来实现对文件的上传和保存,Struts其实是在其基础上做了进一步的封装,更加简单易用.至于文件下载,Struts贯彻AOP 思想,在下载之前提供对用户权限控制的API. 下面我们将详细介绍上传和下载的相关内容. 一.Struts文件上传机制 想要实现文件上传功能,页面的表单的method属性必须被指定为post,还有enctype属性必须为multipart/form-data,该值表示上传的内容将会以二进

  • vue-cli+axios实现文件上传下载功能(下载接收后台返回文件流)

    vue-cli+axios实现附件上传下载记录: 上传: 这里用formData格式传递参数:请求成功后后台返回上传文件的对应信息. 重点是下载: ############## downloadfile(res) { var blob = new Blob([res.data], {type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=utf-8'}); //applicati

随机推荐