【WEEK5】 【DAY2】File Upload and Download【English Version】

2024.3.26 Tuesday

10. File Upload and Download

10.1. Preparation

  1. File upload is one of the most common features in project development. Spring MVC supports file upload well, but the Spring MVC context does not assemble MultipartResolver by default, so it cannot handle file uploads by default. If you want to use Spring’s file upload function, you need to configure MultipartResolver in the context.
  2. Requirements for the front-end form: To upload files, the form’s method must be set to POST, and enctype must be set to multipart/form-data. Only in this case, the browser will send the user-selected files as binary data to the server.
  3. Detailed explanation of the enctype attribute in the form:
    • application/x-www=form-urlencoded: The default way, it only processes the value attribute in the form fields, and the form fields’ values are processed into URL encoding.
    • multipart/form-data: This encoding method will handle form data in a binary stream manner. This method will encapsulate the content of the file specified by the file field into the request parameters, without character encoding.
    • text/plain: Other than converting spaces to “+” signs, other characters are not encoded. This method is suitable for sending emails directly through the form.
  4. Once the enctype is set to multipart/form-data, the browser will process the form data in a binary stream manner. The processing of file uploads involves parsing the original HTTP response on the server side. In 2003, the Apache Software Foundation released the open-source Commons FileUpload component, which quickly became the best choice for Servlet/JSP programmers to upload files.
    • The Servlet 3.0 specification already provides methods to handle file uploads, but this type of upload needs to be completed in the Servlet.
    • Spring MVC provides a simpler encapsulation.
    • Spring MVC provides direct support for file uploads, implemented by a plug-and-play MultipartResolver.
    • Spring MVC uses the Apache Commons FileUpload technology to implement a MultipartResolver implementation class: CommonsMultipartResolver. Therefore, Spring MVC’s file upload still depends on the Apache Commons FileUpload component.

10.2. Basic Configuration

10.2.1. Create a module named springmvc-08-file

Add web support, modify web.xml (same as in springmvc-07-interceptor), modify Tomcat configuration
These operations have been repeated multiple times, so this time only the modified parts are detailed.
Insert image description here

10.2.2. Create a controller folder, applicationContext.xml file

Insert image description here

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- Automatically scan the specified package, all annotated classes are managed by the IOC container -->
    <context:component-scan base-package="P29.controller"/>
    <!-- Static resource filtering -->
    <mvc:default-servlet-handler />
    <mvc:annotation-driven/>

    <!-- View Resolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          id="internalResourceViewResolver">
        <!-- Prefix -->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <!-- Suffix -->
        <property name="suffix" value=".jsp" />
    </bean>

    <!-- File upload configuration -->
    <bean id="multipartResolver"  class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- Request encoding format, must be consistent with the JSP's pageEncoding attribute to correctly read the form's content, default is ISO-8859-1 -->
        <property name="defaultEncoding" value="utf-8"/>
        <!-- Upload file size limit, in bytes (10485760=10M) -->
        <property name="maxUploadSize" value="10485760"/>
        <property name="maxInMemorySize" value="40960"/>
    </bean>

</beans>
  • Common methods of CommonsMultipartFile:
    • String getOriginalFilename(): Gets the original name of the uploaded file
    • InputStream getInputStream(): Gets the file stream
    • void transferTo(File dest): Saves the uploaded file to a directory file

10.3. File Upload

10.3.1. Import the jar package for file upload: commons-fileupload in this module’s pom.xml

Maven will automatically import its dependency package, commons-io package

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>SpringMVC_try1</artifactId>
        <groupId>com.kuang</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>P29</groupId>
    <artifactId>springmvc-08-file</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!-- File Upload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>
        <!-- Import a higher version of servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>
    </dependencies>

</project>

Insert image description here
Import the lib directory in project structure
Insert image description here

10.3.2. Modify index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <%--Submit a file in binary stream form--%>
  <form action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post">
    <input type="file" name="file"/>
    <input type="submit" value="upload">
  </form>
  </body>
</html>

10.3.3. Create FileController.java

package P29.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.*;

@Controller
public class FileController {
    // Use CommonsMultipartFile to receive files
    //@RequestParam("file") encapsulates the file obtained from the name=file control into a CommonsMultipartFile object
    // For bulk upload, CommonsMultipartFile would be an array
    @RequestMapping("/upload")
    public String fileUpload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {

        // Get the file name: file.getOriginalFilename();
        String uploadFileName = file.getOriginalFilename();

        // If the file name is empty, go directly back to the homepage!
        if ("".equals(uploadFileName)){
            return "redirect:/index.jsp";
        }
        System.out.println("Upload file name: " + uploadFileName);

        // Save the upload path settings
        String path = request.getServletContext().getRealPath("/upload");
        // If the path does not exist, create one
        File realPath = new File(path);
        if (!realPath.exists()){
            realPath.mkdir();
        }
        System.out.println("Upload file save address: " + realPath);

        InputStream is = file.getInputStream(); // File input stream
        OutputStream os = new FileOutputStream(new File(realPath, uploadFileName)); // File output stream

        // Read and write
        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len = is.read(buffer)) != -1){
            os.write(buffer, 0, len);
            os.flush();
        }
        os.close();
        is.close();
        return "redirect:/index.jsp";
    }
}

10.3.4. Using file.TransferTo to Save Uploaded Files

Modify FileController.java by adding the fileUpload2 method

package P29.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.*;

@Controller
public class FileController {
    //CommonsMultipartFile to receive files
    //@RequestParam("file") encapsulates the file obtained from the file control into a CommonsMultipartFile object
    //For batch upload, CommonsMultipartFile can be an array
    @RequestMapping("/upload")
    public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException {

        //Get file name: file.getOriginalFilename();
        String uploadFileName = file.getOriginalFilename();

        //If the file name is empty, go directly back to the homepage!
        if ("".equals(uploadFileName)){
            return "redirect:/index.jsp";
        }
        System.out.println("Upload file name : "+uploadFileName);

        //Setting up the save path for upload
        String path = request.getServletContext().getRealPath("/upload");
        //If the path does not exist, create one
        File realPath = new File(path);
        if (!realPath.exists()){
            realPath.mkdir();
        }
        System.out.println("Upload file save address:"+realPath);

        InputStream is = file.getInputStream(); //File input stream
        OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //File output stream

        //Reading and writing (through IO)
        int len=0;
        byte[] buffer = new byte[1024];
        while ((len=is.read(buffer))!=-1){
            os.write(buffer,0,len);
            os.flush();
        }
        os.close();
        is.close();
        return "redirect:/index.jsp";
    }

    /*
     * Using file.TransferTo to save uploaded files
     */
    @RequestMapping("/upload2")
    public String  fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {

        //Setting up the save path for upload
        //Not getting the file name of the uploaded file, directly save the file
        String path = request.getServletContext().getRealPath("/upload");
        File realPath = new File(path);
        if (!realPath.exists()){
            realPath.mkdir();
        }
        //Upload file address
        System.out.println("Upload file save address:"+realPath);

        //Directly write files through CommonsMultipartFile's method (not through IO) (note at this time)
        file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));

        return "redirect:/index.jsp";
    }

}

10.3.5. Running

http://localhost:8080/springmvc_08_file_war_exploded/
Insert image description here
Insert image description here
The uploaded files can be found in the specified location.
Insert image description here

10.4. File Download

10.4.1. Steps for File Download

  1. Set the response header.
  2. Read the file — InputStream.
  3. Write out the file — OutputStream.
  4. Perform the operation.
  5. Close the streams (open last, close first).

10.4.2. Code Implementation (Modify FileController.java)

package P29.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

@Controller
public class FileController {

//  Below is the code for downloading images
    @RequestMapping(value="/download")
    public String downloads(HttpServletResponse response , HttpServletRequest request) throws Exception{
        // The image's download path (here, we hope to download an image named "Screenshot1.png" from /upload)
        String  path = request.getServletContext().getRealPath("/upload");
        String  fileName = "Screenshot1.png";

        //1. Set response header
        response.reset(); // Set the page to not cache, clear buffer
        response.setCharacterEncoding("UTF-8"); // Character encoding
        response.setContentType("multipart/form-data"); // Binary data transfer
        // Set the response header
        response.setHeader("Content-Disposition",
                "attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));

        File file = new File(path, fileName);
        //2. Read the file — input stream
        InputStream input=new FileInputStream(file);
        //3. Write out the file — output stream
        OutputStream out = response.getOutputStream();

        byte[] buff =new byte[1024];
        int index=0;
        //4. Perform the write-out operation
        while((index= input.read(buff))!= -1){
            out.write(buff, 0, index);
            out.flush();
        }
        out.close();
        input.close();
        return null;
    }

}

10.4.3. Run

http://localhost:8080/springmvc_08_file_war_exploded/download
Insert image description here
The file is downloaded to the browser’s specified save location.
Insert image description here

  • 32
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值