<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"; } }
此種方式只能上傳單個文件,不能一次上傳多個文件。html
此種方式不能上傳較大的文件,超過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攔截器的引用必須位於默認攔截器棧以前,不然能上傳文件,但起不到限制文件類型、大小的做用。session
鼠標點擊 <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方法,賦給對應的成員變量,再根據這些成員變量的值來檢測上傳文件是否符合要求。運維
上面有一個成員變量 private ContentTypeMatcher matcher; 可用於檢測上傳文件的內容,好比檢測上傳的視頻是否包含色情畫面。dom
此攔截器類中有一個static、final類型的成員變量:jsp
private static final long serialVersionUID = -4764627478894962478L;
這個UID是此攔截器類共有的,且初次賦值後不能再被修改,用於檢測此攔截器是否已執行。ide
上傳一個文件時,會先調用咱們配置的fileUpload攔截器來檢測文件是否符合要求,而後再調用默認的攔截器棧。默認的攔截器棧中有fileUpload攔截器。this
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>
<result name="input">/upload.jsp</result> </action>
使用input指定表單頁面,上傳出錯時回顯到表單頁面,並顯示錯誤信息。
經常使用的有2種方式
UUID即通用惟一識別碼,能惟一標識某個東西。
UUID產生的這個字符串包含32個十六進制數,用4根連詞線-分爲5段,示例: bd95572b-7fcf-46b2-ae3e-6087d66db40f ,8-4-4-4-12的形式