Spring Boot (30) 上傳文件

文件上傳html

  上傳文件和下載文件是Java Web中常見的一種操做,文件上傳主要是將文件經過IO流傳輸到服務器的某一個文件夾下。java

導入依賴web

  在pom.xml中添加上spring-boot-starter-web和spring-boot-starter-thymeleaf的依賴spring

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

配置文件apache

默認狀況下SPring Boot無需作任何配置也能實現文件上傳的功能,但有可能因默認配置不符而致使文件上傳失敗問題,因此瞭解相關配置信息更有助於咱們對問題的定位和修復。緩存

spring:
  #禁用thymeleaf緩存
  thymeleaf:
    cache: false
  servlet:
    multipart:
      #是否支持批量上傳(默認true)
      enabled: true
      #上傳文件的臨時目錄(通常不用修改)
      location:
      max-file-size: 1048576
      #上傳請求最大爲10M(默認10M)
      max-request-size: 10485760
      #文件大小閥值,當大於這個閥值時將寫入到磁盤,不然存在內存中(默認值0 通常不用修改)
      file-size-threshold: 0
      #判斷是否要延遲解析文件(至關於懶加載 通常不用修改)
      resolve-lazily: false

若是隻容許1M如下的文件,當超出該範圍則會拋出如下錯誤tomcat

org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: 
the request was rejected because its size (20738021) exceeds the configured maximum (10485760)

 

上傳頁面服務器

在src/main/resources下新建static,在static中新建一個index.html的模板文件,實現單文件上傳、多文件上傳、BASE64編碼三種上傳方式,其中BASE64的方式在對Android/IOS/H5等方面仍是不錯的app

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上傳</title>
</head>
<body>


<h2>單一文件上傳示例</h2>
<div>
    <form method="POST" enctype="multipart/form-data" action="/uploads/upload1">
        <p>
            文件1:<input type="file" name="file"/>
            <input type="submit" value="上傳"/>
        </p>
    </form>
</div>

<hr/>
<h2>批量文件上傳示例</h2>

<div>
    <form method="POST" enctype="multipart/form-data" action="/uploads/upload2">
        <p>
            文件1:<input type="file" name="file"/>
        </p>
        <p>
            文件2:<input type="file" name="file"/>
        </p>
        <p>
            <input type="submit" value="上傳"/>
        </p>
    </form>
</div>

<hr/>
<h2>Base64文件上傳</h2>
<div>
    <form method="POST" action="/uploads/upload3">
        <p>
            BASE64編碼:<textarea name="base64" rows="10" cols="80"></textarea>
            <input type="submit" value="上傳"/>
        </p>
    </form>
</div>

</body>
</html>

控制層spring-boot

  建立一個FileUploadController,其中@GetMapping的方式用來跳轉index.html頁面,而@PostMapping相關方法則是對應的單文件上傳、多文件上傳、BASE64編碼三種方式

@Request("file")此處的file對應的就是html中的name="file"的input標籤,而將文件真正寫入的仍是藉助的commons-io中的FileUtils.copyInputStreamToFile(inputStream,file)

package com.spring.boot.controller;

import org.springframework.stereotype.Controller;
import org.springframework.util.Base64Utils;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/uploads")
public class FileUploadController {

    @PostMapping("/upload1")
    @ResponseBody
    public Map<String,String> upload1(@RequestParam("file")MultipartFile imgFile,HttpServletRequest request) throws IOException {
        // 獲取文件名
        String fileName = imgFile.getOriginalFilename();
        // 獲取圖片後綴
        String extName = fileName.substring(fileName.lastIndexOf("."));
        if(extName.equals(".jpg")){
            // 自定義的文件名稱
            String trueFileName=String.valueOf(System.currentTimeMillis())+fileName;
            // 設置存放圖片文件的路徑
            String path="/Users/baidawei/Downloads/imgUpload/" +trueFileName;
            // 開始上傳
            imgFile.transferTo(new File(path));
        }

        Map<String, String> result = new HashMap<>(16);
        result.put("contentType", imgFile.getContentType());
        result.put("fileName", imgFile.getOriginalFilename());
        result.put("fileSize", imgFile.getSize() + "");
        return result;
    }

    @PostMapping("/upload2")
    @ResponseBody
    public List<Map<String,String>> upload2(@RequestParam("file") MultipartFile [] files) throws IOException {
        if(files ==null || files.length == 0){
            return null;
        }

        List<Map<String,String>> results = new ArrayList<>();

        for(MultipartFile file : files){
            String path="/Users/baidawei/Downloads/imgUpload/" + file.getOriginalFilename();
            file.transferTo(new File(path));

            Map<String, String> map = new HashMap<>(16);
            map.put("contentType", file.getContentType());
            map.put("fileName", file.getOriginalFilename());
            map.put("fileSize", file.getSize() + "");
            results.add(map);
        }
        return results;
    }

    @PostMapping("/upload3")
    @ResponseBody
    public void upload3(String base64) throws IOException {
        // TODO BASE64 方式的 格式和名字須要本身控制(如 png 圖片編碼後前綴就會是 data:image/png;base64,)
        final File tempFile = new File("/Users/baidawei/Downloads/imgUpload/test.jpg");
        // TODO 防止有的傳了 data:image/png;base64, 有的沒傳的狀況
        String[] d = base64.split("base64,");
        final byte[] bytes = Base64Utils.decodeFromString(d.length > 1 ? d[1] : d[0]);
        FileCopyUtils.copy(bytes,tempFile);
    }

}

 

啓動項目進行測試:

http://localhost:8088/

上傳單個返回:

{"fileName":"sunwukong.jpg","fileSize":"199556","contentType":"image/jpeg"}

上傳多個圖片 返回:

[{"fileName":"獅子頭.jpg","fileSize":"187554","contentType":"image/jpeg"},{"fileName":"mh1.jpg","fileSize":"260842","contentType":"image/jpeg"}]

Base64編碼轉換地址:http://base64.xpcha.com/pic.html

須要先把圖片轉換爲base64編碼後 再上傳

相關文章
相關標籤/搜索