Struts 2 文件下载

1. 文件下载的路径问题,当项目运行时MyEclipse会把项目加载到Tomcat的webapps目录下面。所以,关于路径问题(一定要设置相对路劲)

2. 相对服务器而言,下载到本地要用相对路径。上传到客户端要用绝对路径好一点

3. 上传文件所需要的包一定不能少


1. Struts 2 对文件下载的支持

Struts 2 通过 org.apache.slruts2.dispatcher.StreamResuIt 结果类型来支持文件下载,

使得原本编写就简单的下载程序变得更加简单了。

StreamResuIt 结果类型利用 HttpServletResponse 对象返回的 ServletOutputStrcam 对象
向客户端输出下载文件的二进制数据, 它有下列参数:

  1. contentType
    发送给 Web 浏览器的数据流的 MIME 类型( 默认是 text/plain ), 即下载文件的内容类型。
    下载文件的类型,客户端向Tomcat请求静态资源的时候,Tomcat会自动在 Response Head 里面添加 “Content-Type” 属性,具体的属性列表配置
  2. contentLength
    数据流的长度, 以字节为单位(浏览器显示一个进度栏), 即下载文件的长度
  3. contentDisposition:
    这个属性配置下载文件的文件名等属性,其中文件类型划分为inline、attachment两种:
    1. inline:浏览器尝试直接打开文件(默认值)
    2. atachment:浏览器直接下载为附件
    这也不是绝对的, 对于浏览器能够显示的下载文件是这样的, 对于浏览器不支持的下载类型, 即使使用 inline 选
    项, 仍然会弹出“ 文件下栽” 对话框。 contentDispostion 的默认值是 inline。
     

  4. inputName
    Action 中用来下载文件的属性的名字, 该属性的类型是 InputStream。 默认认值是inputStream
     

    inputName用于指定下载文件的输入流入口,在Action中需要指定该输入流入口。即要求Action中定义对应属性,该属性类型为InputStream。缺省为inputStream

    如果在Action中声明的是getInputStream()方法,在配置文件struts.xml中配置为<param name="inputName">inputStream</param>

    如果在Action中声明的是getTargetFile()方法,在配置文件struts.xml配置为<param name="inputName">targetFile</param>

  5. bufferSize
    文件数据从输入复制到输出的缓冲区的大小, 默认为 1024 字节
  6. allowCaching
    是否允许缓存

StreamResult 结果类型已经在 struts-default 文件中定义, 逻辑名为 stream。

<result name="success" type="stream">
				<param name="contentType">text/plain</param>
				<param name="inputName">inputStream</param>
                //此处的filename是要下载的文件显示的文件名
				<param name="contentDisposition">attachment;filename="hello.txt"</param>
				<param name="bufferSize">1024</param>
			</result>


注意  

2. 案例

  <body>
	<s:debug/>
	<s:a href="download?fileName=a.txt">download方式一</s:a>
	<a href="download?fileName=a.txt">down方式二</a>
  </body>

public class DownloadAction extends ActionSupport {

	private String fileName;

	public InputStream getInputStream() throws IOException {
		String path = ServletActionContext.getServletContext().getRealPath(fileName);
		/**
		 * 方法一 File file = new File(path); return new FileInputStream(file);
		 * 方法二FileUtils.openInputStream(file);
		 */
		File file = new File(path);
		return FileUtils.openInputStream(file);

	}

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	@Override
	public String execute() throws Exception {

		return super.execute();
	}

	public void setInputStream(InputStream inputStream) {
	}

}
	    <action
			name="download"
			class="action.DownloadAction">
			<result name="success" type="stream">
				<param name="contentType">text/plain</param>
				<param name="inputName">inputStream</param>
				<param name="contentDisposition">attachment;filename="hello.txt"</param>
				<param name="bufferSize">1024</param>
			</result>
		</action>

此时一定不要忘记导入包,还有FileUtils到导入的包是哪个,看仔细了import org.apache.commons.io.FileUtils;

缺点或改进

缺点
 

  1. 如果你要下栽任意目录下的文件( 而不仅限于Web应用程序目录 ),那么只需要修改 action中返回文件输入流的方式即可 ,例 如return new FileInputStream(inputPath)。
  2. 在实际应用中, 下栽的文件不应该在 struts.xml 文件中配置, 如果是这样, 那就等于将 FileDownloadAction 的功能限制为了只下载一个文件。 下载文件的选取应该通过编码来实现, 根据浏览器传来的下载请求, 查询配置文件或数据库, 获取真实下载文件数据, 构造 inputStream 对象
  3. 对于下载的文件名、 下载的文件类型都是在 struts.xml 文件中配置。 如果有许多不同类型的文件要提供给用户下载, 那么这种方式显然有失灵活性。
     

改进

  1. 为了能动态设置文件类型和下载的文件名, 我们可以编写一个拦截器, 在 Action 执行完毕, result 执行之前, 动态添加 StreamResult 的参数。
  2. 为了能够在 result 执行之前截获调用, 我们需要用到 PreResultListener 接口, 该接口可以通过 Actionlnvocation注册, 在 Action 执行完毕, result 执行之前得到一个回调。PreResultListener 需要在拦截器中进行注册, 所以我们需要编写一个拦截器, 然后在
    拦截器方法中注册一个 PreResultListener 实例。

关于下载文件的错误

  1. java.lang.IllegalArgumentException: Can not find a java.io.InputStream with the name [inputStream] in the invocation stack. 
    Check the <param name="inputName"> tag specified for this action.
    	at org.apache.struts2.result.StreamResult.doExecute(StreamResult.java:234)
    
    ERROR DefaultDispatcherErrorHandler Exception occurred during processing request: 
    
    java.lang.IllegalArgumentException: Can not find a java.io.InputStream with the name [inputStream] in the invocation stack.
     Check the <param name="inputName"> tag specified for this action.

这个是因为ServletActionContext.getServletContext().getResourceAsStream(path+fileName);返回的值为null造成的。 也就是说:文件的路径错误。

这个是因为ServletActionContext.getServletContext().getResourceAsStream(path+fileName);返回的值为null造成的。
也就是说:文件的路径错误。

猜你喜欢

转载自blog.csdn.net/qq_40803626/article/details/89208329