NIO实现文件的下载,采用零拷贝,快速高效

前言

因为传统IO文件传输速率低,所以选择了NIO进行文件的下载操作。NIO还有一个好处就是其中零拷贝可以实现减少内存中数据的重复,减少CPU操作的效果。所以相对于传统IO,NIO有着效率高点的优势。

NIO实现文件下载工具类

NIO零拷贝下载的工具类,可以直接使用。

package com.zhao.annotationaop.utils;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.file.Files;
import java.nio.file.Paths;

/**NIO文件下载工具类
 * @author zhao
 */
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);
    }

}

测试

首先编写一个Controller进行测试:
DocDownloadTestController

package com.zhao.annotationaop.controller;

import com.zhao.annotationaop.utils.NioDownloadUtils;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Controller
public class DocDownloadTestController {

    @RequestMapping("/download.do")
    public void download(HttpServletRequest request, HttpServletResponse response){
        String url = request.getParameter("url");
        if (StringUtils.isEmpty(url)){
            throw new RuntimeException("文件文件为空");
        }
        try {
            NioDownloadUtils.downloadDoc(url,response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

注意:这里不要使用@RestController注解,要使用@Controller注解

测试一下

  • 启动项目
  • 在浏览器中输入网址加上要下载的文件的路径:http://localhost:8083/download.do?url=C:%5CUsers%5C32596%5CDesktop%5Cnacos%E6%9E%B6%E6%9E%84%E5%92%8C%E5%8E%9F%E7%90%86.pdf

注意这里的参数是经过URL编码之后的。因为在浏览器请求的的时候,地址栏中的地址会进行URL编码之后才会去请求。所以这里需要先编码之后在请求。
在这里插入图片描述

在这里插入图片描述


版权声明:本文为weixin_46897073原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。