Struts2 in Java file upload download function instance resolution

  • 2020-04-01 03:37:27
  • OfStack

This article illustrates the struts2 file upload and download function in Java. Share with you for your reference. Specific analysis is as follows:

1. File upload

The first is the code for the JSP page

Define an upload tag in the JSP page
 

<tr>
     <td align="right" bgcolor="#F5F8F9"><b> Attachment: </b></td>
     <td bgcolor="#FFFFFF">
     <input type="file" name="upload" />
     </td>
     <td bgcolor="#FFFFFF"> </td>
</tr>

Then there are the related attributes defined in the BaseAction and the rest are omitted (you can also define it in your own Action and replace the access modifier)
 
/**
*Action The base class
**/
public class BaseAction extends ActionSupport {
    protected List<File> upload;
    protected List<String> uploadContentType; //File type
    protected List<String> uploadFileName;    //File name
    protected String savePath;                //Save path
}

Then there is an upload method in the Action. The code is as follows:
/**
  * 8. To upload attachments
  * @param upload
  */
  public void uploadAccess(List<File> upload){
        try {
            if (null != upload) {
                for (int i = 0; i < upload.size(); i++) {
                    String path = getSavePath() + ""+ getUploadFileName().get(i);
                    System.out.println(path);
                    item.setAccessory(getUploadFileName().get(i));
                   
                    FileOutputStream fos = new FileOutputStream(path);
                    FileInputStream fis = new FileInputStream(getUpload().get(i));
                    byte[] buffer = new byte[1024];
                    int len = 0;
                    while ((len = fis.read(buffer)) > 0) {
                        fos.write(buffer, 0, len);
                    }
                    fis.close();
                    fos.close();
                }
            }
        } catch (Exception e) {
            logger.error(" Error uploading attachment. ", e);
        }
}

Then my struts2.xml file
<action name="itemRDAction_*" class="itemRDAction" method="{1}">
     <param name="savePath">e:upload</param>
     <interceptor-ref name="defaultStack">
           <param name="fileUpload.allowedTypes">
               application/octet-stream,image/pjpeg,image/bmp,image/jpg,image/png,image/gif,image/jpeg,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel
           </param>
           <param name="fileUpload.maximumSize">8000000</param>
     </interceptor-ref>
     <result name="show_item_rd_upd">  /WEB-INF/jsp/page_item/updItem_rd.jsp</result>
     <result name="show_item_rd_list"> /WEB-INF/jsp/page_item/listItem_rd.jsp</result>
     <result name="show_item_rd_push"> /WEB-INF/jsp/page_item/pushItem_rd.jsp</result>
</action>

Fileupload.allowedtypes are used to limit the file size of the uploaded file type fileupload.maximumsize

2. File download

The first is the download link in the page

<tr>
   <td width="20%" align="right" bgcolor="#F5F8F9"><b> Attachment: </b></td>
   <td width="40%" bgcolor="#FFFFFF">
   <div style="width:355px; float: left;">${item.accessory}</div>
       <c:if test="${!empty item.accessory}">
           <div class="btn_img" style="float: left;"><a style="color: black; text-decoration: none;" href="download.action?filename=${item.accessory}"> download </a></div>
       </c:if>
   </td>
   <td width="40%" bgcolor="#FFFFFF"> </td>
</tr>

Next is the code for the DownloadAction:
/**
 * DownloadAction
 *
 * @author zhaoxz
 *
 */
@Controller("downloadAction")
@Scope("prototype")
public class DownloadAction extends BaseAction {
    /**
     *
     */
    private static final long serialVersionUID = -4278687717124480968L;
    private static Logger logger = Logger.getLogger(DownloadAction.class);
    private String filename;
    private InputStream inputStream;
    private String savePath;
    private String mimeType;
    public InputStream getInputStream() {
        try {
            String path = getSavePath() + "//"+ new String(filename.getBytes("ISO8859-1"), "utf-8");
            System.out.println(path);
            mimeType = ServletActionContext.getServletContext().getMimeType(path)+ ";charset=UTF-8";
            inputStream = new FileInputStream(path);
            String agent = request.getHeader("USER-AGENT");
            System.out.println(agent);
            if (null != agent) {
                if (-1 != agent.indexOf("Firefox")) {// Firefox
                    mimeType = mimeType.replace("UTF-8", "ISO8859-1");
                } else {// IE7+ Chrome
                    System.out.println("IE,Chrome");
                    filename = new String(filename.getBytes("ISO8859-1"),"utf-8");
                    filename = java.net.URLEncoder.encode(filename, "UTF-8");
                }
            }
        } catch (Exception e) {
            logger.error(" Error downloading file information. ", e);
        }
        if (null == inputStream) {
            System.out.println("getResource error");
        }
        return inputStream;
    }
    public void setInputStream(InputStream inputStream) {
        this.inputStream = inputStream;
    }
    @Override
    public String execute() throws Exception {
        return SUCCESS;
    }
   
    public String getSavePath() {
        return this.savePath;
    }
    public void setSavePath(String savePath) {
        this.savePath = savePath;
    }
    public String getFilename() {
        return filename;
    }
    public void setFilename(String filename) {
        this.filename = filename;
    }
}

Then its struts2.xml file:
 
<action name="download" class="downloadAction">
    <param name="savePath">E:/upload</param>
    <result type="stream">
          <param name="contentType">${mimeType}</param>
          <param name="contentDisposition">attachment;filename="${filename}"</param>
          <param name="inputName">inputStream</param>
    </result>
</action>

If you download it, notice that the encoding format should be fine.

Problems encountered during the upload process

1. Upload large files on error resolution 1

The errors are as follows:

1, the 2012-02-24 11:06:31, 937 ERROR (. Org. Apache struts 2. Dispatcher. The dispatcher, 512) - Could not find the action or result
No result defined for action com. Iman. Portal. Action. QuestionActionImpl and result problemPage - action - file: E: / / myeclipse/workspaces/portal/WebRoot/WEB - INF/classes/struts 2 / struts - question. XML: 51:55
2, the request was rejected because its size (2973652) exceeds the configured maximum (2097152).

The request was rejected because its size (2973652) exceeded the configured maximum (2097152).
Considering the user experience, it is necessary to intercept such exceptions when uploading attachments. The solution is as follows:

1. The uploaded files are stored in the cache first during the uploading process. For security, a temporary storage path is added to the struts.properties file of the project, although the physical path of the server has been set in the project.
 

   struts.multipart.saveDir=/temp

2. Considering that the file upload size may be changed later, the following configuration is added in the struts.properties file of the project, whether by default or not:
    <!--  The size of the files allowed to be uploaded 2M -->
    <constant name="struts.multipart.maxSize" value="2097152"/>

3. Struts.xml configuration
 
   <!--  Modify the problem method  -->
    <action name="updateProblem" method="updateProblem">
      <interceptor-ref name="fileUpload"/>
      <interceptor-ref name="defaultStack" />
     <result name="input">/page/question/page/problemPage.jsp</result>
    </action>

The most important and crucial step

The fileUpload interceptor determines the file type and size only after the file is uploaded to the server. If we do nothing in the Action, the exception will be exposed to the user, so we thought of a way to set the exception information to the Action level error message. Override the addActionError method.
 

@Override
   public void addActionError(String anErrorMessage) {
    //So let's make sure that this is the error that we want to replace before we handle
    if (anErrorMessage.startsWith("the request was rejected because its size")) {
        Pattern pattern = Pattern.compile("d+");
        Matcher m = pattern.matcher(anErrorMessage);
        //Matches
once         m.find();       
        String s1 =m.group();//Uploaded file size
        //Match
again         m.find();       
        String s2 =m.group();//Restricted size & cake;                     < br / >         if(!s1.equals("") && !s2.equals("")){
            fileUploadErrorMessage=" The file size you uploaded ( " +  Long.valueOf(s1)/1024 +" Bytes) exceeding the allowed size ( " + Long.valueOf(s2)/1024/1024 + "M ) ";
            getRequest().setAttribute("fileUploadErrorMessage"," The file is too large to be allowed ("+Long.valueOf(s2)/1024/1024+"M) , upload failed! ");
            //Replace the information with
            super.addActionError(fileUploadErrorMessage);
            }
        } else {//Otherwise, handle
the same way as before             super.addActionError(anErrorMessage);
        }
}

Yes, return to the page with < S: fielderror / > < S: fielderror / > , get the error content in the addActionError.

Because I'm not going to show you the reason for the error on the page, I want to pop up a prompt, so I put the information in the request object.

When the page is loaded, the following js validation is added:

//

    var message="${request.fileUploadErrorMessage}";
        if(message!=null && ""!=trim(message) && message!="null"){
            self.parent.diag.close();
        alert(message);
        return;
}

Here are some references to learn more about dongdong:

Struts.multipart. MaxSize controls the maximum Size of the files uploaded for the entire project
Struts.multipart. MaxSize and the maximumSize attribute of the fileUpload interceptor have different division of labor, which is summarized as follows:

1. The struts. Multipart. MaxSize control upload files by the Size of the largest of the entire project.
  Exceed this size, the background error, the program can not handle such a large file. In fielderror there are the following prompts:
  The request was rejected because its size (16272982) exceeds the configured maximum (9000000).
2. The maximumSize attribute of the fileUpload interceptor must be less than the value of struts.multipart.maxsize.
  Struts.multipart. MaxSize defaults to 2M. When maximumSize is greater than 2M, the value of struts.multipart. MaxSize must be set to be greater than maximumSize.
3. When the uploaded file is larger than struts.multipart.maxsize, the system reports an error
  When the uploaded file is between struts.multipart.maxsize and maximumSize, the system prompts:
  File too large: File "MSF concept. PPT "" upload_5133e516_129ce85285f_ffa_00000005.tmp" 6007104
  When the uploaded file is smaller than maximumSize, the upload is successful.

<action name="UploadFile" class="com.buptisc.srpms.action.UploadFileAction">
            <result name="UploadFileResult">/pages/ShowOtherFiles.jsp</result>
            <result name="JGBsuccess">/pages/JGBdetail.jsp</result>
            <interceptor-ref name="fileUpload">
                <param name="savePath">/data</param> 
                <param name="maximumSize">52428800</param>
            </interceptor-ref>
            <interceptor-ref name="defaultStack"></interceptor-ref>
</action>

Uploading large files on error resolution 2:

Problem: uploading large files to report an error...
Solution: modify the parameters in the struts.xml file as follows

<constant name="struts.multipart.maxSize" value="55000000"/>
<action name="UploadFile" class="com.buptisc.srpms.action.UploadFileAction">
            <result name="UploadFileResult">/www.jb51.net/ ShowOtherFiles.jsp</result>
            <result name="JGBsuccess">/pages/JGBdetail.jsp</result>
            <interceptor-ref name="fileUpload">
                <param name="savePath">/data</param> 
                <param name="maximumSize">52428800</param>
            </interceptor-ref>
            <interceptor-ref name="defaultStack"></interceptor-ref>
</action>

Struts.xml file size vs. actual file size: 1048576 (Bytes) = 1024*1024 = 1M actual file size.
Struts.multipart. MaxSize controls the maximum Size of the files uploaded for the entire project
Struts.multipart. MaxSize and the maximumSize attribute of the fileUpload interceptor have different division of labor, which is summarized as follows:

1. The struts. Multipart. MaxSize control upload files by the Size of the largest of the entire project. Exceed this size, the background error, the program can not handle such a large file. In fielderror there are the following prompts:
The request was rejected because its size (16272982) exceeds the configured maximum (9000000).
2. The maximumSize attribute of the fileUpload interceptor must be less than the value of struts.multipart.maxsize.
Struts.multipart. MaxSize defaults to 2M. When maximumSize is greater than 2M, the value of struts.multipart. MaxSize must be set to be greater than maximumSize.
3. When the uploaded file is larger than struts.multipart.maxsize, the system reports an error
When the uploaded file is between struts.multipart.maxsize and maximumSize, the system prompts:
File too large: File "MSF concept. PPT "" upload_5133e516_129ce85285f_ffa_00000005.tmp" 6007104
When the uploaded file is smaller than maximumSize, the upload is successful.

Restrictions on the type of files to upload

Configure the fileupload interceptor

The defaultStack of struts2 already contains the fileupload interceptor. If you want to add the allowedTypes parameter, you need to write a new defaultStack, copy it and modify it:

<interceptors>  
             <interceptor-stack name="myDefaultStack">
                <interceptor-ref name="exception"/>
                <interceptor-ref name="alias"/>
                <interceptor-ref name="servletConfig"/>
                <interceptor-ref name="i18n"/>
                <interceptor-ref name=www.jb51.net/>
                <interceptor-ref name="chain"/>
                <interceptor-ref name="debugging"/>
                <interceptor-ref name="profiling"/>
                <interceptor-ref name="scopedModelDriven"/>
                <interceptor-ref name="modelDriven"/>
                <interceptor-ref name="fileUpload">
                  <param name="allowedTypes">
                     image/png,image/gif,image/jpeg
                  </param>
                </interceptor-ref>
                <interceptor-ref name="checkbox"/>
                <interceptor-ref name="staticParams"/>
                <interceptor-ref name="actionMappingParams"/>
                <interceptor-ref name="params">
                  <param name="excludeParams">dojo..*,^struts..*</param>
                </interceptor-ref>
                <interceptor-ref name="conversionError"/>
                <interceptor-ref name="validation">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="workflow">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
            </interceptor-stack>
</interceptors>
<default-interceptor-ref name="myDefaultStack"></default-interceptor-ref>

Only in the code
<interceptor-ref name="fileUpload">
  <param name="allowedTypes">
     image/png,image/gif,image/jpeg
  </param>
</interceptor-ref>

 
Interceptors stack at < Package> Tags < Action> The outer TAB configuration is not needed if we define it as the default interceptor as shown above

< Action> In the tag, if not, you need to introduce an interceptor

<action>
       <result name="input">/error/dbError.jsp</result>
       <interceptor-ref name="myDefaultStack"></interceptor-ref>
</action>

   
Action returns input directly, so there is no need to return "input" in action.
 
Also available in < Package> Outside of the label define upload ask your path and size:
<constant name="struts.multipart.saveDir" value="/upload/detailed"></constant>
<constant name="struts.multipart.maxSize" value="1024"></constant>

The most important point: the form to upload the file must be added: enctype="multipart/form-data" without input error.

I hope this article has been helpful to your Java programming.


Related articles: