<s:form action="HandlerAction" method="POST" enctype="multipart/form-data"> <s:file name="profile" label="头像" /> <%-- <s:file name="profile" label="头像" accept="image/jpeg" size="102400" /> --%> <s:submit value="提交" /> </s:form>
public class HandlerAction extends ActionSupport { private File profile; private String profileFileContentType; private String profileFileName; public File getProfile() { return profile; } public void setProfile(File profile) { this.profile = profile; } public String getProfileFileContentType() { return profileFileContentType; } public void setProfileFileContentType(String profileFileContentType) { this.profileFileContentType = profileFileContentType; } public String getProfileFileName() { return profileFileName; } public void setProfileFileName(String profileFileName) { this.profileFileName = profileFileName; } @Override public String execute() throws Exception { System.out.println("开始上传"); //取session中取出user,保存在user目录下。getRealPath()取的是绝对路径。 String user = (String) ServletActionContext.getRequest().getSession().getAttribute("user"); String dirPath = ServletActionContext.getServletContext().getRealPath("/upload") + "/" + user; File dir = new File(dirPath); if (!dir.exists()){ dir.mkdirs(); } File file = new File(dirPath + "/" + profileFileName); //将临时文件保存到指定文件中(正式文件) profile.renameTo(file); //虽然gc每隔一段时间会自动清理,但使用完就删除是最好的。 profile.delete(); System.out.println("上传成功"); return "success"; } }
此种方式只能上传单个文件,不能一次上传多个文件。
此种方式不能上传较大的文件,超过4M的文件就上传不了。
在struts.xml中给处理文件上传的action配置拦截器:
<action name="HandlerAction" class="action.HandlerAction"> <interceptor-ref name="fileUpload"> <param name="allowedTypes">image/jpeg,image/png,image/gif</param> <!-- <param name="allowedExtensions">jpg,png,gif</param> --> <param name="maximumSize">102400</param> </interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> <result name="success">/success.jsp</result> </action>
注意:fileUpload拦截器的引用必须位于默认拦截器栈之前,否则能上传文件,但起不到限制文件类型、大小的作用。
鼠标点击 <interceptor-ref name="fileUpload"> 中的fileUpload,Ctrl+B查看此拦截器的定义:
public class FileUploadInterceptor extends AbstractInterceptor { private static final long serialVersionUID = -4764627478894962478L; protected static final Logger LOG = LogManager.getLogger(FileUploadInterceptor.class); protected Long maximumSize; protected Set<String> allowedTypesSet = Collections.emptySet(); protected Set<String> allowedExtensionsSet = Collections.emptySet(); private ContentTypeMatcher matcher; private Container container; public FileUploadInterceptor() { }
我们在struts.xml中使用<param>传入的文件类型、扩展名、最大尺寸这些参数,执行时会调用此拦截器类的setter方法,赋给对应的成员变量,再根据这些成员变量的值来检测上传文件是否符合要求。
此拦截器类中有一个static、final类型的成员变量:
private static final long serialVersionUID = -4764627478894962478L;
这个UID是此拦截器类共有的,且初次赋值后不能再被修改,用于检测此拦截器是否已执行。
上传一个文件时,会先调用我们配置的fileUpload拦截器来检测文件是否符合要求,然后再调用默认的拦截器栈。默认的拦截器栈中有fileUpload拦截器。
JVM先if判断UID是不是long型的默认初始值:
如果默认拦截器栈在前,里面的fileUplaod是未配置参数的,使用默认值,默认有大小限制,类型、扩展名可以是任意的。
执行我们自己配置的fileUplaod拦截器时,JVM一检测UID,认为此拦截器执行过了,直接跳过(就像过安检,按流程走一次就ok,不会让你再来一次),我们自己配置的fileUpload是没有起到作用的。
上传多个文件时,上传的每个文件都会被fileUpload拦截器拦截(进站的每个人都需要过安检)。
如果不用限制上传文件的类型、大小,则不必自己配置fileUpload拦截器,使用默认的拦截器栈就ok。
fileUpload拦截器是有默认参数的,如果自己没有配置fileUpload拦截器的参数,默认上传文件的最大尺寸为4M,超过4M直接进入服务器报错页面。
把上传文件在服务器上的保存位置写死在代码中,后续维护时如果要改保存位置,运维看不懂代码,还得让你来改,很麻烦。
通常的做法是:
<action name="HandlerAction" class="action.HandlerAction">
<!-- 注意路径中的\要写成\\或者/ --> <param name="savePath">D:/upload</param>
<interceptor-ref name="fileUpload"> <param name="allowedTypes">image/jpeg,image/png,image/gif</param> <param name="maximumSize">102400</param> </interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref>
<result name="success">/success.jsp</result> </action>
<s:form action="HandlerAction" method="POST" enctype="multipart/form-data"> <s:file name="upload" label="上传文件一" /> <s:file name="upload" label="上传文件二" /> <s:submit value="提交" /> </s:form>
是把多个文件保存到一个数组中,一个文件即一个数组元素。注意name相同,都是action中的数组名。
<input type="file" name="upload" multiple="multiple">
<s:file />没有multiple属性,一个<s:file />只能选择1个文件,要一次性选择多个文件,需要使用<input />。
public class HandlerAction extends ActionSupport { private File[] upload; private String[] uploadFileContentType; private String[] uploadFileName; public File[] getUpload() { return upload; } public void setUpload(File[] upload) { this.upload = upload; } public String[] getUploadFileContentType() { return uploadFileContentType; } public void setUploadFileContentType(String[] uploadFileContentType) { this.uploadFileContentType = uploadFileContentType; } public String[] getUploadFileName() { return uploadFileName; } public void setUploadFileName(String[] uploadFileName) { this.uploadFileName = uploadFileName; } private String savePath; public String getSavePath() { return savePath; } public void setSavePath(String savePath) { this.savePath = savePath; } @Override public String execute() throws Exception { File dir = new File(savePath); if (!dir.exists()){ dir.mkdirs(); } if(upload!=null) { for (int i = 0; i < upload.length; i++) { File file = new File(savePath + "/" + uploadFileName[i]); //将临时文件保存到指定文件中(正式文件) upload[i].renameTo(file); //删除临时文件 upload[i].delete(); System.out.println(uploadFileName[i]+"上传成功"); } } return "success"; } }
换成数组罢了,处理时遍历数组即可。
<action name="HandlerAction" class="action.HandlerAction">
<param name="savePath">D:/upload</param>
<interceptor-ref name="fileUpload">
<param name="maximumSize">102400000</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
<result name="success">/success.jsp</result>
</action>
原文:https://www.cnblogs.com/chy18883701161/p/11487730.html