使用response对象下载文件

工作中碰到使用Java下载文件的情况,对一些特殊情况纠结了很久,总算解决了,记录下对下载问题的探究过程以及中间碰到的坑。


一、使用response下载

使用response对象的正常下载

response.reset();
response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8"));
response.setHeader("Connection", "close");
response.setHeader("Content-Type", "application/octet-stream");
		
OutputStream ops = null;
FileInputStream fis =null;
byte[] buffer = new byte[8192];
int bytesRead = 0;
		
try {
    ops = response.getOutputStream();
    fis = new FileInputStream(path);
    while((bytesRead = fis.read(buffer, 0, 8192)) != -1){
         ops.write(buffer, 0, bytesRead);
    }
    ops.flush();
    } catch (IOException e) {
	e.printStackTrace();
    } finally {
	try {
	    if(fis != null){
		fis.close();
	    }
	    if(ops != null){
		ops.close();
	    }
	} catch (IOException e) {
	    e.printStackTrace();
	}
}


二、多个文件下载的情况

开始想使用response进行多个文件的下载,在后端处理,结果无法实现。

坑一:一个request只能返回对应的一个response

因此,无法把多个文件使用response对象进行下载。如果不关闭ops,强行输出到一个文件中,则文件会不可读。使用Excel恢复可读,也只有第一个文件存在。

后来就想尝试发送多个请求,就使用Ajax尝试多次发送请求。

坑二:不能使用Ajax请求下载文件

因为Ajax的返回类型是json、text、html、xml等类型,不是流类型,所以无法实现文件下载。

所以,只能使用隐藏表单或者iframe的方法。

隐藏表单方法:

jQuery('<form action="'+url+'" method="post">' + 
    '<input type="text" name="filename" value="'+filename+'"/>' + 
    '<input type="text" name="filetype" value="'+filetype+'"/>' + 
    '</form>').appendTo('body').submit();
存在的问题是提交时会全部加到一起,只提交一次。

最终解决方法:

页面添加多个隐藏iframe,循环设置src,分别load


三、Ajax请求实现文件下载方法

1、使用隐藏表单,提交隐藏表单

2、使用window.open()或window.location.href()方法

3、使用隐藏iframe,src指向后端需要的地址


四、Ajax无法进行文件下载,但仍可以获得文件内容,文件将被保留在内存中,无法保存到磁盘。因为JavaScript无法与磁盘进行交互,js无法调用到浏览器的下载处理机制和程序,会被浏览器阻塞。


五、response的getWriter()方法在连续输出两次流到页面的时候,第二次的流会包括第一次的流,所以需用response.reset()或response.resetBuffer()方法来重置

response.reset()

Clears any data that exists in the buffer as well as the status code and headers. If the response has been committed, this method throws an IllegalStateException.

response.reset()的使用有一个条件受限:response的任何打开流关闭之后都不能再reset

resetBuffer()

Clears the content of the underlying buffer in the response without clearing headers or status code. If the response has been committed, this method throws an

IllegalStateException

可以看到resetBuffer方法与reset方法的区别是,头和状态码没有清除

六、多个文件下载还可以通过将多个文件压缩到一个压缩包再行下载

java将多个文件一起打成zip包后下载实例

  • 10
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用以下步骤实现: 1. 在登录请求中,验证用户的用户名和密码是否正确。 2. 如果验证通过,则使用 response 对象将用户的头像图片发送给浏览器,浏览器可以通过访问该 URL 来下载图片。 3. 如果验证不通过,则返回错误信息给用户。 以下是示例代码: ```java @WebServlet("/login") public class LoginServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); if (username.equals("admin") && password.equals("admin123")) { // 如果用户名和密码验证通过 // 将用户的头像图片发送给浏览器 response.setContentType("image/jpeg"); FileInputStream fis = new FileInputStream("path/to/image.jpg"); OutputStream os = response.getOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len = fis.read(buffer)) != -1) { os.write(buffer, 0, len); } fis.close(); os.flush(); os.close(); } else { // 如果用户名或密码不正确 response.setContentType("text/plain;charset=UTF-8"); response.getWriter().write("用户名或密码不正确"); } } } ``` 在上面的代码中,我们首先读取了用户提交的用户名和密码,然后进行验证。如果验证通过,我们设置 response 对象的 content type 为 "image/jpeg",表示我们将要发送的是一张图片。然后使用 FileInputStream 读取图片文件,将图片的内容写入 response 对象的 output stream 中,最后关闭 FileInputStream 和 OutputStream。如果验证不通过,我们设置 content type 为 "text/plain;charset=UTF-8",表示我们将要发送的是一段纯文本内容,然后使用 response.getWriter() 获取一个 PrintWriter 对象,将错误信息写入 PrintWriter 中,最后关闭 PrintWriter。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值