首页 > 其他分享 >【SSM】文件下载的两种方式

【SSM】文件下载的两种方式

时间:2022-12-02 17:32:48浏览次数:38  
标签:文件 文件名 filename SSM 缓冲区 response 下载

文件下载的两种方式


今天项目中用到了一个文件下载的方式,将一个app放在服务器上,可以直接下载,刚开始想到了使用输出文件流的方式,思路有了,就直接上手写了,参考网上的资料,整理出来了一个根据文件名,下载。后来同事一句话提醒了我,直接放在服务器上,就能下载,开始感觉这个好像不行,怎么能直接访问这个呢?开玩笑吧???

后来脑海中一瞬间闪到一个画面,就是调试的时候,静态资源的访问,不是直接下载的js文件吗?直接访问这个文件试试呢,于是试了之后发现真的好使。

第一种:文件名和大小都是固定的

这种的就比较简单了,可以直接将文件放在项目的某一个文件夹下,简单粗暴。然后在配置文件中,将此文件夹配置成静态资源文件夹,这样就可以直接访问了。

一般是spring-mvc.xml文件里面,配置js,image等静态资源文件的地方

	<!-- 配置静态资源的访问映射,此配置中的文件,将不被前端控制器拦截 -->
	<mvc:resources location="/static/" mapping="/static/**" />
	<mvc:resources location="/apk/" mapping="/apk/**" />

然后就可以直接在浏览器中直接访问这个文件就可以下载了。

http://192.168.17.31:8080/monitor-pay/apk/checkPay.apk
第二种:文件有很多,文件名不固定

这种就可以利用输出文件流的方式了,在controller类里面写一个方法,接收参数为文件名,这样就可以实现下载了。

    @RequestMapping(value="checkPay",method=RequestMethod.GET)
    public void download(HttpServletRequest request,HttpServletResponse response,String filename) throws IOException {
    	//checkPay.apk为需要下载的文件
    	//String filename = "checkPay.apk";   //我这里使用的是一个固定的文件,方法可以不用写filename参数
    	//获取文件的绝对路径名称,apk为根目录下的一个文件夹,这个只能获取根目录文件夹的绝对路径
        String path = request.getSession().getServletContext().getRealPath("apk")+"\\"+filename;
        System.out.println(path);
        
        //得到要下载的文件
        File file = new File(path);
        if (!file.exists()) {
        	response.setContentType("text/html; charset=UTF-8");//注意text/html,和application/html
        	response.getWriter().print("<html><body><script type='text/javascript'>alert('您要下载的资源已被删除!');</script></body></html>");
        	response.getWriter().close(); 
            System.out.println("您要下载的资源已被删除!!");  
            return;  
		}
        //转码,免得文件名中文乱码  
        filename = URLEncoder.encode(filename,"UTF-8");  
        //设置文件下载头  
        response.addHeader("Content-Disposition", "attachment;filename=" + filename);    
        //1.设置文件ContentType类型,这样设置,会自动判断下载文件类型    
        response.setContentType("multipart/form-data"); 
        // 读取要下载的文件,保存到文件输入流
        FileInputStream in = new FileInputStream(path);
        // 创建输出流
        OutputStream out = response.getOutputStream();
        // 创建缓冲区
        byte buffer[] = new byte[1024]; // 缓冲区的大小设置是个迷  我也没搞明白
        int len = 0;
        //循环将输入流中的内容读取到缓冲区当中
        while((len = in.read(buffer)) > 0){
        	out.write(buffer, 0, len);
        }
        //关闭文件输入流
        in.close();
        // 关闭输出流
        out.close();
    }
}

刚开始是按照网上千变一律的写法,BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());

不知道为什么,用到我这里下载速度很慢很慢,几k,几k的下载,并且手机浏览器下载还会出现中断和下载不动的问题,失败率几乎百分百,PC端下载有那么一两次成功的,这就很不正常了,开始以为是客户服务器的原因,因为服务器操作起来特别的卡顿。。。。。。

后来又查了些资料,借鉴这篇博客里的下载文件的方式,添加了一个缓冲区,效果明显的改善了,2.7M的apk秒下载那种。

关于缓冲区的作用,度娘上的这位大侠的解释,很形象,但是缓冲区的大小问题,我还是没明白:

终风且暴
就是这么说吧,我打个比方
一个人要把水龙头流出来的水弄到水缸里面去,要是没有缓冲池,每流出一滴水,你都要跑两趟水龙头与缸之间的距离(这个在传文件的时候就是磁盘读写的时间),而当你有一个缓冲池(比如盆),你可以等盆满了再把水弄过去(这之间你可以做其他的事,在JAVA中,你就是CPU)……
所以有缓冲区的话,你可以节省CPU的大量时间,而且可以对缓冲区中的数据进行集中读写,这样不必每来一个数据你去到磁道上搜索地址,然后再回来接受数据,再去搜索地址存取数据,再回来接受数据。
缓冲区的大小根据你的用户的上传文件的大小设置,一般取平均值,这个要经验的。注意:缓冲区大小不是上传文件的平均值大小……


下载中文文件时,需要注意的地方就是中文文件名要使用URLEncoder.encode方法进行编码(URLEncoder.encode(fileName, "字符编码")),否则会出现文件名乱码。
修改这一句:

response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(filename, "UTF-8"));

在Springboot中导出文件,按照上面写的还是中文乱码,则试下下面的方式:

fileName = URLEncoder.encode(fileName, "UTF-8");//postman测试中文文件名再次被编码,待前端测试是否正常
response.addHeader("Content-Disposition", "attachment;filename*=utf-8'zh_cn'" + fileName);
response.setContentType("multipart/form-data");
out = response.getOutputStream();

标签:文件,文件名,filename,SSM,缓冲区,response,下载
From: https://blog.51cto.com/linmengmeng/5907348

相关文章

  • vue文件分片上传,断点续传
    ​ 1 背景用户本地有一份txt或者csv文件,无论是从业务数据库导出、还是其他途径获取,当需要使用蚂蚁的大数据分析工具进行数据加工、挖掘和共创应用的时候,首先要将本地文......
  • Eclipse中建立struts2的配置文件struts.xml
    Eclipse中建立struts2的配置文件struts.xml的步骤:1、解压最新的struts2包文件,我用的是:struts-2.5.16-all.zip(上Struts的官网下载),然后找到struts-2.5.dtd所在路径并复制......
  • Python——将PPT和Word转为PDF文件
    前言通过win32com.client将PPT和Word文件转为PDF格式内容importfitz#pipinstallpymupdfimportwin32com.clientimportosdefppt2pdf(filename,output_file......
  • arcgis的asc文件排序是从大到小
    在arcgis中加载   ......
  • 使用node上传文件到文件夹
    1、安装multer和path:npminstallmultermulter-sOryarnaddmultermulter-s2、新建upload.js://1.引入constexpress=require('express');constmulter......
  • tif文件拼接+转换成netcdf格式
     2022-11-1611:33 手上有若干个SRTM1V3.0的高程数据,为HGT格式,需要将其拼接并转换成netcdf格式,以让ncl能够进行读取步骤:gdal_translateA.hgtA.tifgdal_merge.py......
  • c#文件分片上传,断点续传
    ​ HTML部分 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="index.aspx.cs" Inherits="up6.index" %><!DOCTYPE html PUBLIC "-//W3C//DTDXH......
  • .NET CORE读取自定义配置文件到Configuration中
    微软只提供了以下可以读取配置的方式,其中文件配置只能读取INI、JSON和XML文件,如果我想对其他自定义文件进行读取,那么我们可以使用自定义配置提供程序进行配置  比如,......
  • Qwt开发笔记(一):Qwt简介、下载以及基础demo工程模板
    前言  QWT开发笔记系列整理集合,这是目前使用最为广泛的Qt图表类(Qt的QWidget代码方向只有QtCharts,Qwt,QCustomPlot),使用多年,系统性的整理,本系列旨在系统解说并逐步更新其各......
  • 使用post接口进行大批量导出文件
    在工作中,使用get方法导出文件会遇到一些问题:url长度限制,传入id量大且加载速度慢,所以抛弃以前的请求下载方式,使用post接口进行请求下载!  本次的导出文件为excel文件,其他......