将表单域的enctype设置为multipart/form-data,在服务器端以二进制流的方式来获取表单信息即可实现文件的上传。
手动解析二进制流可能有些繁琐,所以有两个上传框架可以实现文件上传:Commons-FileUpload和COS。
struts2则是进一步封装,让上传下载都极大简化了。
表单的enctype属性
有以下三种:
application/x-www-form-urlencoded:正常情况下我们没有设置enctype属性,便是使用这个默认值,它将表单的value属性值处理成url编码的方式。
multipart/form-data:以二进制流的方式处理表单数据,这种编码方式会把文件域的内容也封装到请求参数中
text/plain:这种方式主要用于直接通过表单发送邮件
如果以第一种是无法上传的,且看:
<%@page language="java" contentType="text/html; charset=GBK"%> <html> <head> <title>文件上传</title> </head> <body> <form action="process.jsp" method="post" enctype="application/x-www-form-urlencoded"> 随便名字:<input type="text" name="name"/><br/> 文件名:<input type="file" name="file"/><br/> <input type="submit" value="上传"/> </form> </body> </html>
<%@page language="java" contentType="text/html; charset=GBK"%> <html> <head> <title>文件上传处理</title> </head> <body> <% request.setCharacterEncoding("GBK"); out.println(request.getParameter("name")); out.println(request.getParameter("file")); %> </body> </html>
<%@page language="java" contentType="text/html; charset=GBK"%> <html> <head> <title>文件上传</title> </head> <body> <form action="process.jsp" method="post" enctype="multipart/form-data"> 随便名字:<input type="text" name="name"/><br/> 文件名:<input type="file" name="file"/><br/> <input type="submit" value="上传"/> </form> </body> </html>
<%@page language="java" contentType="text/html; charset=GBK"%> <%@page import="java.io.*" %> <% InputStream is = request.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String buffer = null; while( (buffer = br.readLine()) !=null) { out.println(buffer + "<br>"); } out.flush(); %>
我上传了一个xml文件,以上是页面结果一部分。
可见,已经获得了文件内容,只要将流中的文件内容解析出来即可。
使用框架的话就简单多了,上传框架会负责解析请求中的所有域,包括表单的文件域和其他表单域。
struts2并没有提供请求解析器,而是使用了Commons-Fileupload框架,并做了进一步的封装,是的文件上传极大简化。当然,也可以使用struts.multipart.parser常量来更换文件上传的解析器。
知道了实现文件上传大概都要做些什么,现在来看看struts2给我们带来的便利。
upload.jsp:
<%@page language="java" contentType="text/html; charset=GBK"%> <html> <head> <title>文件上传</title> </head> <body> <form action="upload.action" method="post" enctype="multipart/form-data"> 文件名字:<input type="text" name="name"/><br/> 文件:<input type="file" name="file"/><br/> <input type="submit" value="上传"/> </form> </body> </html>
public class UploadAction { private String name; private File file; private String fileContentType; private String fileFileName; private String savePath; public String execute() throws IOException{ FileOutputStream out = new FileOutputStream(new File(getSavePath()+"\\"+getFileFileName())); BufferedInputStream br = new BufferedInputStream(new FileInputStream(getFile())); byte[] buf = new byte[1024]; while(br.read(buf)!= -1){ out.write(buf); } out.close(); br.close(); return "success"; } public String getSavePath() { return ServletActionContext.getRequest().getRealPath(savePath); } public void setSavePath(String savePath) { this.savePath = savePath; } public String getName() { return name; } public void setName(String name) { this.name = name; } public File getFile() { return file; } public void setFile(File file) { this.file = file; } public String getFileContentType() { return fileContentType; } public void setFileContentType(String fileContentType) { this.fileContentType = fileContentType; } public String getFileFileName() { return fileFileName; } public void setFileFileName(String fileFileName) { this.fileFileName = fileFileName; } }
另外,一个File域xxx在action类中应对应三个属性:xxxFileName,xxxContentType,xxx。savaPath是在xml文件中指定的,看如下action配置:
<?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.enable.DynamicMethodInvocation" value="false" /> <package name="default" namespace="/" extends="struts-default"> <global-results> <result name="error">/error.jsp</result> </global-results> <global-exception-mappings> <exception-mapping exception="java.lang.Exception" result="error"/> </global-exception-mappings> <action name="upload" class="ch6.fileupload.UploadAction"> <param name="savePath">/fileupload</param> <result name="success">/fileupload/result.jsp</result> <result name="error">/conversion/error.jsp</result> </action> </package> </struts>
另外,struts2已经定义了拦截器用于控制上传文件的类型过滤和大小限制:
<action name="upload" class="ch6.fileupload.UploadAction"> <interceptor-ref name="fileUpload"> <param name="maximumSize">20000</param> <param name="allowedTypes">image/bmp</param> </interceptor-ref> <interceptor-ref name="defaultStack"/> <param name="savePath">/fileupload</param> <result name="success">/fileupload/result.jsp</result> <result name="error">/conversion/error.jsp</result> </action>
实现多个文件的上传
在upload.jsp中:定义多个file域,并让他们name相同。
在action中:定义File[] upload,String[] uploadFileName,String[] contentType,在execute()对每个file处理即可。也可以使用List来保存File和String
其他的都一样了。