SpringBoot的文件上傳功能與下載方式


Spring對文件上傳做了簡單的封裝,就是用MultipartFile這個對象去接收文件,當然有很多種寫法,下面會一一介紹。

文件的下載很簡單,給一個鏈接就行,而這個鏈接怎么生成,也有很多方式,下面也會講解下常用的方式。

application.properties 中需要添加下面的配置:

spring.servlet.multipart.enabled=true
spring.servlet.multipart.max-file-size=20MB
spring.servlet.multipart.max-request-size=50MB

  

這里,

  • spring.servlet.multipart.max-file-size是對單個文件大小的限制。
  • spring.servlet.multipart.max-request-size是對單次請求的大小進行限制

至此,已經可以正常的進行上傳下載了,就剩下寫代碼了。

文件上傳的幾種方式

在Controller的RequestMapping注解的方法參數中,直接將MultipartFile作為參數傳遞進來。

 

package com.cff.springbootwork.web.file;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.cff.springbootwork.dto.ResultModel;
import com.cff.springbootwork.service.UploadService;

@RestController
@RequestMapping("/file")
public class FileRest {
	private Logger log = LoggerFactory.getLogger(this.getClass());

	@Value("${upload.static.url}")
	private String uploadStaticUrl;

	@Autowired
	UploadService uploadService;

	@RequestMapping("/upload")
	public ResultModel upload(@RequestParam("files") MultipartFile file) {
		try {
			if (file.isEmpty()) {
				return ResultModel.error("文件不能為空!");
			}
			String fileName = uploadService.saveUploadFile(file);
			return ResultModel.ok(uploadStaticUrl + fileName);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("文件上傳失敗!", e);
			return ResultModel.error("文件上傳失敗!");
		}
	}
}

  

測試的時候,使用postman可以這樣傳參:

 

 

 

 

2.2 多個文件上傳

在Controller的RequestMapping注解的方法參數中,直接將MultipartFile作為list傳遞進來。在FileRest中增加uploadList方法。

 
package com.cff.springbootwork.web.file;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.cff.springbootwork.dto.ResultModel;
import com.cff.springbootwork.service.UploadService;

@RestController
@RequestMapping("/file")
public class FileRest {
	private Logger log = LoggerFactory.getLogger(this.getClass());

	@Value("${upload.static.url}")
	private String uploadStaticUrl;

	@Autowired
	UploadService uploadService;

	@RequestMapping("/upload")
	public ResultModel upload(@RequestParam("files") MultipartFile file) {
		try {
			if (file.isEmpty()) {
				return ResultModel.error("文件不能為空!");
			}
			String fileName = uploadService.saveUploadFile(file);
			return ResultModel.ok(uploadStaticUrl + fileName);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("文件上傳失敗!", e);
			return ResultModel.error("文件上傳失敗!");
		}
	}

	@RequestMapping("/uploadList")
	public ResultModel uploadList(@RequestParam("files") List<MultipartFile> fileList) {
		try {
			List<String> list = new ArrayList<>();
			for (MultipartFile file : fileList) {
				String fileName = uploadService.saveUploadFile(file);
				list.add(uploadStaticUrl + fileName);
			}
			return ResultModel.ok(list);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("文件上傳失敗!", e);
			return ResultModel.error("文件上傳失敗!");
		}
	}
}

  

測試的時候,使用postman可以這樣傳參:

 

 

 

 

 

從HttpServletRequest中取文件

新建uploadByRequest方法,將HttpServletRequest作為參數,Spring自動傳入。

Spring對Request做了一層封裝,如果有文件,它就是MultipartHttpServletRequest。

然后我們可以從MultipartHttpServletRequest獲取到MultipartFile。后面的處理方式一樣了。

package com.cff.springbootwork.web.file;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.cff.springbootwork.dto.ResultModel;
import com.cff.springbootwork.service.UploadService;

@RestController
@RequestMapping("/file")
public class FileRest {
	private Logger log = LoggerFactory.getLogger(this.getClass());

	@Value("${upload.static.url}")
	private String uploadStaticUrl;

	@Autowired
	UploadService uploadService;

	@RequestMapping("/upload")
	public ResultModel upload(@RequestParam("files") MultipartFile file) {
		try {
			if (file.isEmpty()) {
				return ResultModel.error("文件不能為空!");
			}
			String fileName = uploadService.saveUploadFile(file);
			return ResultModel.ok(uploadStaticUrl + fileName);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("文件上傳失敗!", e);
			return ResultModel.error("文件上傳失敗!");
		}
	}

	@RequestMapping("/uploadList")
	public ResultModel uploadList(@RequestParam("files") List<MultipartFile> fileList) {
		try {
			List<String> list = new ArrayList<>();
			for (MultipartFile file : fileList) {
				String fileName = uploadService.saveUploadFile(file);
				list.add(uploadStaticUrl + fileName);
			}
			return ResultModel.ok(list);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("文件上傳失敗!", e);
			return ResultModel.error("文件上傳失敗!");
		}
	}

	@RequestMapping("/uploadByRequest")
	public ResultModel uploadByRequest(HttpServletRequest request) {
		try {
			Map<String, MultipartFile> files = new HashMap<>();

			if (request instanceof MultipartHttpServletRequest) {
				MultipartHttpServletRequest req = (MultipartHttpServletRequest) request;
				MultiValueMap<String, MultipartFile> multiValueMap = req.getMultiFileMap();
				if (multiValueMap != null && !multiValueMap.isEmpty()) {
					for (String key : multiValueMap.keySet()) {
						files.put(key, multiValueMap.getFirst(key));
					}
				}
			}
			if (files.isEmpty())
				return ResultModel.error("文件木有?");

			List<String> list = new ArrayList<>();
			for (MultipartFile file : files.values()) {
				String fileName = uploadService.saveUploadFile(file);
				list.add(uploadStaticUrl + fileName);
			}
			return ResultModel.ok(list);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("文件上傳失敗!", e);
			return ResultModel.error("文件上傳失敗!");
		}
	}
}

  

測試的時候,傳參方式使用上面兩種都可以了。

三、文件下載方式

文件上傳成功后,我們同時會提供下載功能。下載功能很簡單,有以下幾種方式:

3.1 Spring配置映射

新建一個WebStaticConfig配置類,實現WebMvcConfigurer接口即可:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebStaticConfig implements WebMvcConfigurer {
	@Value("${upload.static.local}")
	private String uploadStaticLocal;

	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/static/**").addResourceLocations("file:" + uploadStaticLocal);
	}

	public String getUploadStaticLocal() {
		return uploadStaticLocal;
	}

	public void setUploadStaticLocal(String uploadStaticLocal) {
		this.uploadStaticLocal = uploadStaticLocal;
	}

}

  

這句話將當前服務器(比如是http://127.0.0.1:8080)的/static路徑(http://127.0.0.1:8080/static/)下的資源,映射到uploadStaticLocal指定的本地路徑下的文件。

然后我們就可以直接訪問文件了。

3.2 代理(nginx)映射

代理首選nginx了。高性能快捷的代理轉發工具。

比如要將http://127.0.0.1:8081/static/下的資源,映射到/static/指定的本地路徑下的文件,可以這樣配置

server {
    listen       8081;
    server_name  localhost;

	location /static {
		alias /static/;
		index index.html;
	}
}

  

這里為什么用8081而不是上面的8080了呢?因為上面的8080端口已經被SpringBoot應用占用了。nginx要在另一個端口監聽了,如果非要將SpringBoot應用和靜態資源在一個端口,可以對SpringBoot應用也做代理,例如:

 

server {
    listen       8081;
    server_name  localhost;

    location ^~ /api/ {
        proxy_pass   http://127.0.0.1:8080/;
    }
    
    location /static {
        alias /static/;
        index index.html;
    }
}

3.3 ResponseEntity讀取文件並返回

比如我們在FileRest的Controller中建立個downloadFile方法,傳入文件名,將文件讀取為byte,包裝成ResponseEntity返回。

 

    @RequestMapping(value = "/downloadFile", method = { RequestMethod.GET })
    public ResponseEntity<byte[]> downloadFile(@RequestParam("fileName") String fileName) {
        try {
            File file = new File(fileName);
            byte[] body = null;
            InputStream is = new FileInputStream(file);
            body = new byte[is.available()];
            is.read(body);
            is.close();
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Disposition", "attchement;filename=" + file.getName());
            HttpStatus statusCode = HttpStatus.OK;
            ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(body, headers, statusCode);
            return entity;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

 


免責聲明!

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



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