1.先来看看文件上传的一些底层的东西
在eclipse新建一个ManualUpload动态web project,然后新建encAppli.jsp 内容如下
<%@ page language="java" contentType="text/html; charset=UTF-8" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>使用application/x-www-form-urlencoded</title> </head> <body> <form action="dealDis.jsp" method="post" enctype="application/x-www-form-urlencoded"> 上传文件 <input name="image" type="file" /><br/> 请求参数: <input name="title" type="text"/><br/> <input name="tj" value="提交" type="submit"/> </form> </body> </html>
上面页面很简单 一个表单 包含一个文件域和一个输入文本域以及一个提交按钮
表单的编码方式使用的是
application/x-www-form-urlencoded----同时也是表单默认的编码方式,只会将表单中value的值使用URL进行编码后传输
接收上面表单提交的dealDis.jsp内容如下
<%@page import="java.io.InputStreamReader"%> <%@page import="java.io.BufferedReader"%> <%@page import="java.io.InputStream"%> <%@ page language="java" contentType="text/html; charset=UTF-8" %> <% out.write("hello world 1<br/>"); InputStream is=request.getInputStream(); BufferedReader br=new BufferedReader(new InputStreamReader(is)); String buffer=null; out.write("hello world 2<br/>"); //out.write(br.readLine()+" hello world 2<br/>"); while((buffer=br.readLine())!=null) { //out.write("hello world 3<br/>"); out.println(buffer+"<br/>"); } out.write("hello world 4<br/>"); %>将上面使用URL进行编码的value的值获取显示在页面上
encAppli.jsp 界面
dealDis.jsp显示界面
刚才在上面提过了 使用application/x-www-form-urlencoded会将value的值进行URL编码 那么现在对上面页面的image=C%3A%5CUsers%5Cundergrowth%5CDesktop%5Cegg%5Czsm%5C6901236378809.png&title=%E4%BA%8C%E7%BB%B4%E7%A0%81%E5
%9B%BE%E7%89%87&tj=%E6%8F%90%E4%BA%A4 进行URL解码
新建URLEnDe.java 内容如下
package com.undergrowth.test; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; public class URLEnDe { /** * @param args * @throws UnsupportedEncodingException */ public static void main(String[] args) throws UnsupportedEncodingException { // TODO Auto-generated method stub String dString="image=C%3A%5CUsers%5Cundergrowth%5CDesktop%5Cegg%5Czsm%5C6901236378809." + "png&title=%E4%BA%8C%E7%BB%B4%E7%A0%81%E5%9B%BE%E7%89%87&tj=%E6%8F%90%E4%BA%A4"; System.out.println(URLDecoder.decode(dString,"UTF-8")); String deString="提交"; String oriString=URLEncoder.encode(deString, "utf-8"); System.out.println(oriString); String iroString="二维码图片"; System.out.println(URLEncoder.encode(iroString, "UTF-8")); } }
控制台输出如下:
image=C:UsersundergrowthDesktopeggzsm6901236378809.png&title=二维码图片&tj=提交
%E6%8F%90%E4%BA%A4
%E4%BA%8C%E7%BB%B4%E7%A0%81%E5%9B%BE%E7%89%87
所以通过对比控制台的输出内容和上面dealDis.jsp输出的内容可知 使用application/x-www-form-urlencoded这种编码方式是没有办法实现文件上传的
现在将encAppli.jsp中的<form action="dealDis.jsp" method="post" enctype="application/x-www-form-urlencoded">改为
<form action="dealDis.jsp" method="post" enctype="multipart/form-data"> 即将表单的编码格式改了
multipart/form-data-----会使用二进制流的方式进行传输表单中的表单域 无论是文件域还是其他的表单域都已二进制流的方式进行传输
dealDis.jsp页面输出内容 可以看到multipart/form编码方式 确实是使用二进制流进行传输的
对于上面的显示界面,还需要改一个地方,就是将encAppli.jsp和dealDis.jsp页面的编码方式均改为GBK,即
<%@ page language="java" contentType="text/html; charset=UTF-8"%>改为 <%@ page language="java" contentType="text/html; charset=GBK"%>
以上即是两种编码方式的区别。
其实看到上面dealDis.jsp页面的输出 我们其实就可以自己写代码来获取上传文件的内容了但是上述代码只能处理文本文件。
如果不使用struts框架的上传功能的话 自己可以使用Commons-FileUpload library或者pell或者cos组件进行相应的文件上传功能,关于文件上传的很多细节,建议参看李刚老师的struts2权威指南的第七章。
使用超链接进行文件的下载 在webcontent目录下放置文件夹imageUp包含如下文件
<a href="imageUp/6901236378809.gif">6901236378809.gif</a><br/> <a href="imageUp/新建 Microsoft Word 文档.doc">新建 Microsoft Word 文档.doc</a><br/>
即可完成文件的下载
2.使用struts2进行文件的上传和下载
struts2文件上传和下载
显示文件上传的界面fileUpload.jsp 内容如下
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>文件上传</title> </head> <body> <s:form action="fileup" namespace="/fu" method="post" enctype="multipart/form-data" > <s:file name="images" label="上传图片"></s:file> <s:file name="images" label="上传图片"></s:file> <s:file name="images" label="上传图片"></s:file> <s:submit value="提交"></s:submit> </s:form> <s:a href="imageUp/6901236378809.gif">6901236378809.gif</s:a><br/> <s:a href="imageUp/新建 Microsoft Word 文档.doc">新建 Microsoft Word 文档.doc</s:a><br/> <s:a href="filedown">下载图片</s:a> </body> </html>
定义了一个表单 包含三个文件域 一个提交按钮 剩余的三个超链接是后面用于下载的
业务控制Action struts.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <constant name="struts.custom.i18n.resources" value="global"></constant> <package name="fu" namespace="/fu" extends="struts-default"> <action name="fileup" class="com.undergrowth.FileUpLoad"> <interceptor-ref name="fileUpload"> <param name="allowedTypes"> image/gif,image/jpg </param> </interceptor-ref> <interceptor-ref name="defaultStack"/> <result name="input">/fileUpload.jsp</result> <result>/WEB-INF/page/success.jsp</result> </action> </package> <package name="down" extends="struts-default"> <action name="filedown" class="com.undergrowth.FileDownLoad"> <result name="success" type="stream"> <param name="contentType">image/gif</param> <param name="inputName">targetFile</param> <param name="contentDisposition">attachment;filename="${fileNameAction}"</param> <param name="bufferSize">4096</param> </result> </action> </package> </struts>
<constant name="struts.custom.i18n.resources" value="global"></constant> 用于加载资源配置文件 里面有文件上传失败的提示信息
接着两个 一个是上传的action 一个是下载的action
fileup的action用于文件的上传 通过引用fileUpload的拦截器和defaultStack的拦截器栈实现功能
在这个地方需要注意一下的是 fileUpload拦截器与defaultStack拦截器的位置 因为defaultStack拦截器栈中是包含fileUpload拦截器的 如果将fileUpload拦截器放在defaultStack的后面 你会发现 即是你上传了不符合allowedTypes类型的文件 依然不会跳转到input视图 原因在于 将fileUpload放在后面会覆盖掉defaultStack的作用 defaultStack拦截器栈里面的validation拦截器就不会起作用了 那么就不会调转到input视图了 我在这个地方搞了一下午 被坑死了
filedown的action用于文件的下载
contentType----限定下载的类型 例如image/gif代表只能是gif图片 text/plain只能是纯文本 text/xml表示只能是xml文件
inputName----用于提供下载文件的内容 这里指向一个InputStream
contentDisposition-----用于指定下载文件的处理方式 attachment表示使用附件的方式(即弹出对话框进行下载) inline---使用内联的方式 即默认会打开
bufferSize----用于指定下载文件的缓存大小
${fileNameAction}----使用el表达式用于解决下载文件中文乱码的问题
success.jsp文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>成功上传文件</title> </head> <body> <ol> <s:iterator value="imagesFileName" status="name"> <li><s:property /> <img src="d:/imageUp/<s:property/>" /> </li> <br/> </s:iterator> </ol> </body> </html>
文件上传的FileUpLoad.java 内容如下
package com.undergrowth; import java.io.File; import java.io.InputStream; import org.apache.commons.io.FileUtils; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; public class FileUpLoad extends ActionSupport{ /** * */ private static final long serialVersionUID = 1L; private String[] imagesFileName; //上传的文件名 public String[] getImagesFileName() { return imagesFileName; } public void setImagesFileName(String[] imagesFileName) { this.imagesFileName = imagesFileName; } public String[] getImagesContentType() { return imagesContentType; } public void setImagesContentType(String[] imagesContentType) { this.imagesContentType = imagesContentType; } public File[] getImages() { return images; } public void setImages(File[] images) { this.images = images; } private String[] imagesContentType; //上传的文件类型 private File[] images; //上传的文件 @Override public String execute() throws Exception { // TODO Auto-generated method stub String pathname="d:\imageUp\"; File destFile=new File(pathname); if(!destFile.exists()) destFile.mkdirs(); for (int i = 0; i < images.length; i++) { FileUtils.copyFile(images[i], new File(destFile, imagesFileName[i])); } return SUCCESS; } }
上面上传action的实现类,提供了三个数组变量,分别用于存储上传文件、上传文件的类型、上传文件的名称,同时将上传的文件保存到本地电脑的D盘目录下
FileDownLoad.java
package com.undergrowth; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; public class FileDownLoad extends ActionSupport{ /** * */ private static final long serialVersionUID = 1L; public void setFileNameAction(String fileNameAction) { this.fileNameAction = fileNameAction; } private String fileNameAction; public String getFileNameAction() { return fileNameAction; } public InputStream getTargetFile() { /*InputStream is = null; try { is = new FileInputStream("D:\imageUp\6901236378810.gif"); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); }*/ return ServletActionContext.getServletContext().getResourceAsStream("imageUp/6901236378817.gif"); } @Override public String execute() throws Exception { // TODO Auto-generated method stub setFileNameAction(new String("下载的图片.gif".getBytes(), "ISO-8859-1")); System.out.println(SUCCESS); return SUCCESS; } }
fileNameAction属性用于解决下载文件中文乱码问题
getTargetFile用于提供下载文件的内容
3.测试界面
输入 http://localhost:8080/strutsMulFile/fileUpload.jsp 显示界面
success.jsp界面
如果上传文件不是gif或者jpg格式则会出错 如下
默认情况下 不是中文 这里是修改了配置文件 global_zh_CN.properties 内容如下
struts.messages.error.content.type.not.allowed=u6587u4EF6u7C7Bu578Bu4E0Du5141u8BB8
这里注意一下 global_zh_CN.properties 文件里面必须是标准的ascii内容 不过eclipse自带的插件会帮我们进行处理
如果用的不是eclipse 则需要使用native2ascii(在java安装路径的bin目录下)工具进行转换 native2ascii src dest
当然 还有很多的值 我们可以自己设定 详情见下表