Struts2 file upload

Upload a single file

Form:

<s:form action="HandlerAction" method="POST" enctype="multipart/form-data">
    <s:file name="profile" label="Head portrait" />
<%-- <s:file name="profile" label="Head portrait" accept="image/jpeg" size="102400" /> --%>
    <s:submit value="Submit" />
</s:form>
  • method="POST" enctype="multipart/form-data" needs to be set.
  • You can use either struts2's or html's form labels.HTML form tags support more attributes, such as multiple attributes.
  • The accept, size attributes do not limit the type or size of the uploaded file.Accept simply specifies the file type in the file selector and can still switch to * (all types).The size property is invalid.

 

 

 

Action:

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("Start uploading");

        //take session Remove from user,Save in user Directory. getRealPath()The absolute path is taken.
        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);
        //Save temporary files to specified files (official files)
        profile.renameTo(file);
        //although gc Clean up automatically every once in a while, but deleting when used is best.
        profile.delete();

        System.out.println("Upload Successful");
        return "success";
    }
}
  • You need to provide a member variable of type File to save temporary files.
  • You also need to provide two corresponding member variables: FileContextType, FileName, to hold the file type, file name, and the Convention naming is: File variable name + FileContextType | FileName.
  • You need to provide getter, setter methods for these three member variables.

 

 

This method can only upload a single file, not multiple files at a time.

This method does not upload large files, and files over 4M cannot be uploaded.

 

 

 

 

 

 

Limit the type and size of uploaded files

Configure interceptors for action s uploaded to processing files in struts.xml:

<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>

Note: The reference to the fileUpload interceptor must precede the default interceptor stack, otherwise the file can be uploaded, but it does not limit the file type and size.

 

 

 

Principle analysis

Mouse click on fileUpload in <interceptor-ref name="fileUpload">, Ctrl+B to see the definition of this interceptor:

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() {
    }

 

The setter method of this interceptor class is invoked on execution, assigned to the corresponding member variables, and then checked to see if the uploaded file meets the requirements based on the values of these member variables.

 

 

 

Why must a reference to the fileUpload interceptor precede the default interceptor stack?

There is a static, final type member variable in this interceptor class:

private static final long serialVersionUID = -4764627478894962478L;

This UID is common to this interceptor class and cannot be modified after initial assignment to detect whether the interceptor has been executed.

When uploading a file, we call our configured fileUpload interceptor to detect if the file meets the requirements, and then call the default interceptor stack.There is a fileUpload interceptor in the default interceptor stack.

 

The JVM first determines if the UID is a long default initial value:

  • Yes: if this interceptor has not been called, then this interceptor will be called
  • No: Explain that this interceptor has already been called, then do not call this interceptor again

If the default interceptor stack is in the front, the fileUplaod inside is not configured with parameters, using the default value, there is a size limit by default, and the type and extension can be arbitrary.

When executing our own configured fileUplaod interceptor, the JVM detects the UID and thinks that the interceptor has been executed, skipping it directly (just like security checks, ok once in a process, won't let you do it again). Our own configured fileUpload does not work.

 

 

When multiple files are uploaded, each file uploaded is blocked by the fileUpload interceptor (everyone who enters the station needs security checks).

 

If you do not limit the type and size of the uploaded file, you do not have to configure the fileUpload interceptor yourself, and use the default interceptor stack.

The fileUpload interceptor has default parameters. If you do not configure the parameters of the fileUpload interceptor yourself, the maximum size of the default upload file is 4M, which exceeds 4M and goes directly to the server error page.

 

 

 

 

 

 

 

Set the location where uploaded files will be saved on the server

Write the save location of the uploaded file on the server in the code. If you change the save location during subsequent maintenance, the operation and maintenance can not understand the code, but you have to change it, which is very troublesome.

 

The usual practice is:

  • Set a member variable, such as savePath, in the action that handles uploaded files to indicate where to save the uploaded files and provide getter, setter methods
  • When configuring action s with struts.xml, use <param>where incoming files are saved
<action name="HandlerAction" class="action.HandlerAction">
     <!-- Notice in the path\To write as\\perhaps/ --> <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>

 

 

 

 

 

 

 

 

 

Upload multiple files simultaneously

form

  • It also means that a form submits multiple file s at a time, which can be used with multiple <s:file/> or <input type="file"/>:
<s:form action="HandlerAction" method="POST" enctype="multipart/form-data">
    <s:file name="upload" label="Upload File One" />
    <s:file name="upload" label="Upload File Two" />
    <s:submit value="Submit" />
</s:form>

Is to save multiple files into an array, a file is an array element.Notice that the names are the same, both are the array names in the action.

 

  • Ctrl can also select multiple files in a single file selector:
<input type="file" name="upload" multiple="multiple">

<s:file /> has no multiple attribute, only one file can be selected for a <s:file />. To select multiple file s at once, you need to use <input />.

 

  • These two ways can be used together.

 

 

 

action

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]);
                //Save temporary files to specified files (official files)
                upload[i].renameTo(file);
                //Delete Temporary Files
                upload[i].delete();
                System.out.println(uploadFileName[i]+"Upload Successful");

            }
        }

        return "success";
    }

}

Change to an array, and traverse the array while processing.

 

 

 

struts.xml

<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>

Keywords: Java Struts xml JSP jvm

Added by Bramme on Fri, 27 Dec 2019 04:44:36 +0200