关于Struts2的文件下载
首先先来说下关于文件下载的原理: 服务端为客户端提供了一个下载服务,所以服务端需要一个输出流(把客户请求下载的文件输出),相对于服务端来说,客户端需要下载接收一个文件,所以它需要一个输入流(接收文件)。 服务器读取要下载文件的内容,用一个Response响应流写回并设置HTTP头信息ContentType(文件类型)、?ContentDisposition(以什么方式打开) 下面给出一个小Demo,具体代码具体分析吧 ? 1、首先是提供下载的页面:download.jsp 给出超链接到Action并用Get方式传递一个文件名进行属性注入 1 <%@ page language="java contentTypetext/html; charset=utf-8 pageEncodingutf-8"%> 2 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 3 <html 4 head 5 Meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" 6 title>下载文件示例</ 7 8 body 9 h2>下载文件10 a href="download.action?filename=照片文件.jpg">点击下载照片文件a11 ="download.action?filename=admin.rar">点击下载压缩包文件12 ="download.action?filename=总结.txt">点击下载文本文件13 14 > ? 2、处理下载文件的Action:DowloadAction.java 这里提供了一个成员变量属性来接收页面传递过来的文件名,由于文件名是以Get方式传递过来的,中文会出现乱码问题,所以在setter方法里需要做一些处理,也就是重新编码。 1 package com.lcw.struts2.dowload; 2 import java.io.File; java.io.FileInputStream; java.io.FileNotFoundException; java.io.IOException; java.io.InputStream; java.io.UnsupportedEncodingException; java.net.URLEncoder; 10 org.apache.struts2.ServletActionContext; 12 sun.misc.BASE64Encoder; 14 15 com.opensymphony.xwork2.ActionSupport; 16 /** 17 * 对于客户端来说它需要下载接收一个文件,也就是说它需要一个输入流 18 * 对于服务端来说它需要对外提供一个下载的服务,也就是说它需要一个输出流 19 */ 20 21 public class DowloadAction extends ActionSupport { 22 23 private String filename;//下载页面传递了该参数,需提供setter方法接收 24 25 void setFilename(String filename) { 26 由于是get方式传递的,中文会出现乱码,不能直接获取,需转码 27 try { 28 this.filename = new String(filename.getBytes("ISO-8859-1"),"utf-8"); 29 } catch (UnsupportedEncodingException e) { 30 e.printStackTrace(); 31 } 32 } 33 34 public String execute(){ 35 System.out.println("正在下载文件:"+filename); 36 return SUCCESS; 37 38 39 为客户端提供输入流 40 public InputStream getInputStream() throws FileNotFoundException{ 41 String srcFile=ServletActionContext.getServletContext().getRealPath("/download")+"/"+filename; 42 File file=new File(srcFile);得到一个file对象 43 return new FileInputStream(file);返回一个文件输入流 44 45 46 根据不同的文件动态给出MIME文件类型 47 String getContentType(){ 48 在Tomcat Conf里的web.xml有对应的映射文件 49 ServletActionContext.getServletContext().getMimeType(filename); 50 51 52 返回一个文件名 53 public String getFilename() IOException{ 54 String agent=ServletActionContext.getRequest().getHeader("user-agent");根据http头信息获取对应的浏览器类型 55 encodeDownloadFilename(filename,agent); 56 57 58 59 下载附件名乱码问题 , IE和火狐 解决不同 IE默认是Url编码 火狐默认是base64编码 60 String encodeDownloadFilename(String filename,String agent) 61 IOException { 62 if (agent.contains("Firefox")) { 火狐浏览器 63 filename = "=?UTF-8?B?" 64 + new BASE64Encoder().encode(filename.getBytes("utf-8")) 65 + "?="; 66 } else { IE及其他浏览器 67 filename = URLEncoder.encode(filename,1)">68 69 filename; 70 71 } 看了上面的代码,如果不清楚这块知识点的朋友可能会有点蒙,别急,下面我来解析下这段代码是怎么来的 首先Struts2的文件下载是通过一个结果集stream来完成的,在Struts2核心包里的struts-default.xml里我们可以找到这样的一句话: result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/> 我们来看下这个类(org.apache.struts2.dispatcher.StreamResult)里面有什么,Ctrl+Shift+T关联下源代码 这个类里面给出了很多参数,因为都有默认值,所以我们不需要全部到去改动它,只需要改变我们需要的地方就可以了。 这里来解释下上面画红色框的参数内容:contentType,contentDisposition,inputName contetType:是下载文件对应的MIME协议类型,比如:text/html,text/plain等,这个参数我们不能写死,因为我们的下载文件的类型有很多,有时是图片,有时是文档等。 contentDisposition:是下载文件的打开方式,这里默认是inline也就是内联在浏览器打开,如果不想关联浏览器我们可以把它设置成attment以附件的形式打开。 inputNmae:这是定义一个返回流(客户端需要的输入流)的名称,属性值为inputStream。 ? 所以我们需要在Action里面提供这些东西,利用JAVA的反射机制让Struts2的配置文件(压入值栈,并给出getter方法)读取到就行了。 这里我们的下载附件名依旧会乱码,因为IE等浏览器默认的编码是URL而火狐浏览器默认的编码是BASE64,我们需要在这里判断客户端使用的是什么浏览器,这个很简单,只需要得到客户端的HTTP头信息Agment就行了,具体代码在上面encodeDownloadFilename方法里以给出,拿来用便是了。 ? 3、再来看下配置文件struts.xml的配置: 由于Action里已给出我们所需参数的getter方法,我们在这边这需要用Ognl表达式取出,就可以根据我们要下载的文件,动态给出所需参数了,没有设置的参数就意味着保持默认值。 <?xml version="1.0" encoding="UTF-8"?> DOCTYPE struts PUBLIC 3 "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" 4 "http://struts.apache.org/dtds/struts-2.0.dtd"struts 6 constant ="struts.devMode" value="true" /> 7 8 <!-- 全局国际化配置 --> 9 ="struts.custom.i18n.resources"="messages"></constant11 package ="struts2test" extends="struts-default"12 action ="download"="com.lcw.struts2.dowload.DowloadAction"13 result type="stream"14 一个流二个头 15 ognl表达式,动态给出不同下载文件相相对应的MIME协议规定的类型 比如:text/html16 在Action里给出getContentType压栈 17 param ="contentType">${contentType}param18 下载文件打开方式 inline浏览器内部打开,attachment 以附件形式打开 19 在Action里动态返回文件名 getFilename 20 ="contentDisposition">attachment;filename=${filename}21 result22 action25 > ? 然后我们新建一个文件夹download,把要下载的文件和web页面提供的文件名一样放入 到这里就大功告成了,看下页面效果吧: (编辑:北几岛) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- .NET Core 3.0 Preview 6中对ASP.NET Core和Blazor的更新
- php – 在cron作业中运行无限循环
- Springboot 系列(二)Spring Boot 配置文件
- Java学习之动态代理篇
- go-admin在线开发平台学习-2[程序结构分析]
- Spring Boot(十二)单元测试JUnit
- php – htmlspecialchars将撇号转换为' for facebook
- 转换流OutputStreamWriter写文本文件,将字符流转成字节流
- php – 一种显示当前登录的WordPress用户网站的Google Ana
- [Go] golang缓冲通道实现管理一组goroutine工作