Spring實現文件的上傳下載


背景:之前一直做的是數據庫的增刪改查工作,對於文件的上傳下載比較排斥,今天研究了下具體的實現,發現其實是很簡單。此處不僅要實現單文件的上傳,還要實現多文件的上傳。

單文件的下載知道了,多文件的下載呢??

我這里使用的spring boot來快速搭建spring mvc框架,賊方便,不用都對不起自己。

本篇博客將講解的是Springmvc的文件上傳和下載功能。對於上傳功能,我們在項目中是經常會用到的,比如用戶注冊的時候,上傳用戶頭像,這個時候就會使用到上傳的功能。而對於下載,使用場景也很常見,比如我們項目中有個使用說明是是pdf版的,會提供給用戶進行下載的功能。相對於來說,這兩個功能都是很常見。

搭建Springmvc開發環境

         使用spring boot來搭建mvc的框架。

文件目錄:

 

pom.xml文件依賴:

<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>spring.boot</groupId>
    <artifactId>uploadfile</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>uploadfile</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--jsp頁面使用jstl標簽 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>

        <!--用於編譯jsp -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <!-- 配置文件上傳的bean 控制文件大大小,編碼等 -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-io -->
        <!-- 使用到其中的FileUtil工具類 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.3.2</version>
        </dependency>



    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

 spring-web.xml:

注入這個bean,控制文件的上傳。

<?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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
                        http://www.springframework.org/schema/aop   
        http://www.springframework.org/schema/aop/spring-aop.xsd">

<!--     <mvc:annotation-driven conversion-service="conversionSerivce" /> -->
    
<bean id="multipartResolver"  
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
    <!-- 默認編碼 -->  
    <property name="defaultEncoding" value="utf-8" />  
    <!-- 文件大小最大值 -->  
    <property name="maxUploadSize" value="80485760" />  
    <!-- 內存中的最大值 -->  
    <property name="maxInMemorySize" value="40960" />  
</bean>  
</beans>

 ps:對於文件大小的控制,在spring boot中出現一個問題,就是xml的配置有時生效,有時不會生效,特別是單文件上傳和多文件上傳時候會導致上傳文件的參數為null。最后的解決辦法是通過顯示的bean注入的方式。

在使用過程中可以將xml中的bean注釋掉,只用下述方式控制即可。

ConfigClass:導入xml文件

package spring.boot.uploadfile.config;

import javax.servlet.MultipartConfigElement;

import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

/**
 * ClassName:ConfigClass <br/>
 * Function: TODO  <br/>
 * Date:     2018年3月2日 下午8:20:05 <br/>
 * @author   prd-lxw
 * @version   1.0
 * @since    JDK 1.7
 * @see      
 */
/**
 * classpath路徑:locations={"classpath:application-bean1.xml","classpath:application-bean2.xml"}
 * file路徑: locations = {"file:d:/test/application-bean1.xml"};
 */
@Configuration
@ImportResource(locations = { "classpath:spring-web.xml" })
//@ImportResource(locations={"file:d:/test/application-bean1.xml"})
public class ConfigClass {

    @Bean public MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        //文件最大  
        factory.setMaxFileSize("1000240KB"); //KB,MB  
        /// 設置總上傳數據總大小  
        factory.setMaxRequestSize("102400KB");
        return factory.createMultipartConfig();
    }

}

 

 

以上配置是spring boot中的內容,此處簡單講解,主要就是mvc框架的搭建。

實現文件上傳的功能

 2.1首先我們來新建一個jsp頁面,命名為:uploadform.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <form action="gotoAction" enctype="multipart/form-data" method="post">
        <table>
            <tr>
                <td>請選擇文件:</td>
                <td><input type="file" name="file"></td>
            </tr>
            <tr>
                <td>開始上傳</td>
                <td><input type="submit" value="上傳"></td>
            </tr>
        </table>
    </form>
</body>
</html>

 ps:上傳頁面jsp的編寫

寫一個上傳的頁面form表單,其中一定要注意的是在表單的屬性中添加entcypt="multipart/form-data",這表示上傳的將會是二進制流的格式,以規定的二進制進行上傳,便於服務器處理,使用post請求:

2.2:再寫一個上傳成功的jsp頁面,主要是用來當上傳成功時候跳轉的頁面,命名為:success.jsp

  <body>
   <h2>文件上傳成功!</h2>  
  </body>

2.3:然后再寫一個上傳失敗的頁面,主要是用來當上傳失敗的時候跳轉的頁面,命名為:error.jsp

<body>
<h2>文件上傳失敗!請檢查文件是否存在</h2>
</body>

2.4:寫好了jsp頁面,接下來就是寫我們的控制器了,Springmvc控制器,我們寫了一個FileUploadController類,然后寫上具體的代碼,如下所示,

注意其中使用MultipartFile來接受form表單傳過來的file文件,MultipartFile有幾個核心的api,可以供我們使用,比如 boolean isEmpty(),用來判斷文件是否為空。void transferTo( File file),把文件寫入目標路徑地址

下屬代碼是最終實驗的Controller中的代碼。后面的詳解因為太累了,直接復制原來的文章。。。。。

/**
 * Project Name:uploadfile
 * File Name:FileUploadController.java
 * Package Name:spring.boot.uploadfile.controller
 * Date:2018年3月2日下午8:28:42
 * Copyright (c) 2018, 深圳金融電子結算中心 All Rights Reserved.
 *
*/

package spring.boot.uploadfile.controller;

import java.io.File;
import java.io.IOException;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import spring.boot.uploadfile.domain.User;

/**
 * ClassName:FileUploadController <br/>
 * Function: 實現spring中的單文件上傳與下載,文件可以作為一個參數傳遞,也可以作為bean的一個屬性傳遞
 * Date:     2018年3月2日 下午8:28:42 <br/>
 * @author   prd-lxw
 * @version   1.0
 * @since    JDK 1.7
 * @see      
 */
@Controller
public class FileUploadController {

    /**
     * 首次進入時候的頁面
     * @param formName
     * @return
     */
    @RequestMapping(value = "/{formName}")
    public String loginForm(@PathVariable String formName) {

        return formName;

    }

    /**
     * 實現單文件的上傳
     * @param file
     * @param request
     * @return
     */
    @RequestMapping(value = "/gotoAction", method = RequestMethod.POST)
    public String upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) {

        if (!file.isEmpty()) {

            String contextPath = request.getContextPath();//"/SpringMvcFileUpload"
            String servletPath = request.getServletPath();//"/gotoAction"
            String scheme = request.getScheme();//"http"

            String storePath = "E:\\testJava\\filesss";//存放我們上傳的文件路徑

            String fileName = file.getOriginalFilename();

            File filepath = new File(storePath, fileName);

            if (!filepath.getParentFile().exists()) {

                filepath.getParentFile().mkdirs();//如果目錄不存在,創建目錄

            }

            try {
                file.transferTo(new File(storePath + File.separator + fileName));//把文件寫入目標文件地址

            } catch (Exception e) {

                e.printStackTrace();

                return "error";

            }

            return "success";//返回到成功頁面

        } else {

            return "error";//返回到失敗的頁面
        }

    }

    /**
     * 將文件作為bean的一個屬性上傳
     * @param user
     * @param request
     * @param map
     * @return
     */
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public String reg(@ModelAttribute User user, HttpServletRequest request, Map<String, Object> map) {

        final String wrong = "error";

        final String good = "success";

        MultipartFile headimage = user.getHeadimage();

        boolean empty = headimage.isEmpty();

        if (!empty) {

            String realPath = request.getServletContext().getRealPath("/images");

            String uploadPath = "E:\\testJava\\filesss";

            String headimageName = headimage.getOriginalFilename();

            File imageFile = new File(uploadPath, headimageName);

            try {

                headimage.transferTo(new File(uploadPath + File.separator + headimageName));

            } catch (Exception e) {

                e.printStackTrace();

                return wrong;

            }
            map.put("user", user);

            return "userinfo";

        } else {
            return wrong;
        }
    }

    /**
     * 實現單文件的下載
     * @param request
     * @param filename
     * @param model
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/download", method = RequestMethod.GET)
    //匹配的是href中的download請求
    public ResponseEntity<byte[]> download(HttpServletRequest request, @RequestParam("filename") String filename, Model model) throws IOException {

        String downloadFilePath = "E:\\testJava\\filesss";//從我們的上傳文件夾中去取

        File file = new File(downloadFilePath + File.separator + filename);//新建一個文件
        //        byte[] body = null;
        //        InputStream is = new FileInputStream(file);
        //        body = new byte[is.available()];
        //        is.read(body);

        HttpHeaders headers = new HttpHeaders();//http頭信息

        String downloadFileName = new String(filename.getBytes("UTF-8"), "iso-8859-1");//設置編碼

        headers.setContentDispositionFormData("attachment", downloadFileName);

        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        //MediaType:互聯網媒介類型  contentType:具體請求中的媒體類型信息

        return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);

    }
}
View Code

 

 

 

User.java

/**
 * Project Name:uploadfile
 * File Name:User.java
 * Package Name:spring.boot.uploadfile.domain
 * Date:2018年3月2日下午8:41:47
 * Copyright (c) 2018, 深圳金融電子結算中心 All Rights Reserved.
 *
*/

package spring.boot.uploadfile.domain;

import java.io.Serializable;

import org.springframework.web.multipart.MultipartFile;

/**
 * ClassName:User <br/>
 * Function: 將文件作為bean的一個屬性
 * Date:     2018年3月2日 下午8:41:47 <br/>
 * @author   prd-lxw
 * @version   1.0
 * @since    JDK 1.7
 * @see      
 */
public class User implements Serializable {//用戶實體類

    /**  */
    private static final long serialVersionUID = 1L;

    private String            userName;

    private MultipartFile     headimage;            //上傳文件會自動綁定到該屬性

   
    //省略getter和setter方法
}

2.5:好了,到此我們就可以實現上傳功能了,發布在Tomact容器里,然后就可以進行上傳文件了。

在瀏覽中輸入:http://localhost:8080/uploadform

具體的頁面請求如下,然后瀏覽具體的文件,點擊上傳按鈕:

點擊瀏覽,上傳

 

然后執行相應的方法,完成文件的上傳。

三:將上傳文件綁定到具體的對象上

  3.1:首先我們來定義一個實體類User,這個實體類中的headimage屬性的主要作用就是用來映射我們上傳的文件,可以看到它是MultipartFile類型的:

 

 

三:將上傳文件綁定到具體的對象上

  3.1:首先我們來定義一個實體類User,這個實體類中的headimage屬性的主要作用就是用來映射我們上傳的文件,可以看到它是MultipartFile類型的:

 

將上傳文件綁定到具體的對象上

  3.1:首先我們來定義一個實體類User,這個實體類中的headimage屬性的主要作用就是用來映射我們上傳的文件,可以看到它是MultipartFile類型的:

public class User implements Serializable{//用戶實體類
    
    private String userName;
    
    private MultipartFile headimage;//上傳文件會自動綁定到該屬性
  
     //省略getter和setter方法
}

3.2:然后寫我們的 jsp上傳頁面,這里我們來模擬一個用戶注冊上傳頭像的場景,新建一個registerForm.jsp頁面,然后寫一個form表單,如下:

<body>
    <h2>用戶注冊</h2>
    <form action="register" enctype="multipart/form-data" method="post">
        <table>
            <tr>
                <td>用戶頭像:</td>
                <td><input type="file" name="headimage"></td>
            </tr>
            <tr>
                <td>上傳:</td>
                <td><input type="submit" value="上傳"></td>
            </tr>
        </table>
    </form>
</body>

 

 3.3:寫我們的方法控制器處理注冊邏輯的層的代碼,注意其中的user對象加入了@ModelAttribute注解,其主要作用是用來映射把上面的form表單的headimage屬性自動注入到對象里面還有Map<String,Object> map主要是為了存放user對象,放在requestScope里面,這樣就可用el表達式把其中的值取出來了

@RequestMapping(value="/register",method=RequestMethod.POST)
    public String reg(@ModelAttribute User user,HttpServletRequest request,Map<String,Object> map){

        final String wrong="error";

        final String good="success";

        MultipartFile headimage = user.getHeadimage();

        boolean empty = headimage.isEmpty();

        if (!empty) {

            String realPath = request.getServletContext().getRealPath("/images");

            String uploadPath="D:\\userUploadFile\\Files";

            String headimageName = headimage.getOriginalFilename();

            File imageFile = new File(uploadPath,headimageName);

            
            try {

                headimage.transferTo(new File(uploadPath+File.separator+headimageName));

            } catch (Exception e) {

                e.printStackTrace();

                return wrong;

            }
            map.put("user", user);

            return "userInfo";

        }else {
            return wrong;
        }
    }

 

3.4:我們來新建一個jsp頁面,取名為userinfo.jsp,其主要作用是顯示剛才的我們的文件名:

<body>
用戶頭像:${requestScope.user.headimage.originalFilename}
</body>

3.5:頁面寫完了,我們在來模擬測試一下,在客戶端Ie瀏覽器中,輸入http://localhost:8080/SpringMvcFileUpload/registerForm:

實現用戶下載的功能

4.1:首先定義一個downinfo.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

      <h3>文件下載</h3>
     <a
        href="download?filename=V.jpeg">
            用戶頭像:V
      </a> 
</body>
</html>

4.2:來看看我們的download控制器代碼:注意download方法返回的是ResponseEntity<byte[]> 類型,這個是封裝好的返回類型,我們需要傳入byte數組、headers、HttpStatus,然后它就會返回具體的下載流,調用客戶端去下載資源

@RequestMapping(value="/download",method=RequestMethod.GET) //匹配的是href中的download請求
    public ResponseEntity<byte[]> download(HttpServletRequest request,@RequestParam("filename") String filename,
            Model model) throws IOException{
        
        String downloadFilePath="D:\\userUploadFile\\Files";//從我們的上傳文件夾中去取
        
        File file = new File(downloadFilePath+File.separator+filename);//新建一個文件
        
        HttpHeaders headers = new HttpHeaders();//http頭信息
        
        String downloadFileName = new String(filename.getBytes("UTF-8"),"iso-8859-1");//設置編碼
        
        headers.setContentDispositionFormData("attachment", downloadFileName);
        
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        
        //MediaType:互聯網媒介類型  contentType:具體請求中的媒體類型信息
        
        return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.CREATED);
        
    }

 

ps:此處注意這兩個類的jar包。

FileUtils來自org.apache.commons.commons-io

 4.3:我們來測試一下寫的東西是否能准確運行,點擊超鏈接,注意此鏈接指向的地址:http://localhost:8080/SpringMvcFileUpload/download?filename="myheadimage".jpg,這就表示這個鏈接會去請求控制器,然后控制器進行處理下載, 這樣就完成了文件的下載功能了:

點擊超鏈接:

 

總結

   本篇博文介紹了SpringMvc上傳和文件的功能,需要注意的地方就是對於文件上傳包common-fileupload.jar包的使用,還有在配置文件上配置mulitipartResolver這個bean。下面又介紹了用java 實體類去映射上傳文件的屬性對應的文件,這點的好處就是它會自動映射,然后把對象放入到我們的請求域中,就可以展示給界面用戶層,這也是mvc思想模式的體現。接下來是介紹去下載文件,只需要從我們的寫入的目標地址去取出文件,再進行responseEntity對象的封裝,就可以實現下載功能

 以上轉載自:https://www.cnblogs.com/wyq178/p/6921164.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM