這篇文章將為大家詳細講解有關Spring Boot 文件上傳與下載,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
創(chuàng)新互聯(lián)公司主營巧家網(wǎng)站建設的網(wǎng)絡公司,主營網(wǎng)站建設方案,成都app軟件開發(fā),巧家h5重慶小程序開發(fā)公司搭建,巧家網(wǎng)站營銷推廣歡迎巧家等地區(qū)企業(yè)咨詢
項目創(chuàng)建
開發(fā)環(huán)境為 Intellij IDEA,項目創(chuàng)建很簡單,按照下面的步驟創(chuàng)建即可:
File -> New -> Project...
選擇 Spring Initializr,點擊 Next
填寫 Group (項目域名) 和 Artifact (項目別名)
構(gòu)建類型可以選擇 Maven 或 Gradle, 看個人習慣
添加 Web 依賴
輸入項目名稱及保存路徑,完成創(chuàng)建
項目創(chuàng)建完畢之后就可以進行開發(fā),項目的完整結(jié)構(gòu)如下圖所示:
參數(shù)配置
項目創(chuàng)建完成之后,需要設置一些必要的參數(shù),打開項目resources
目錄下配置文件application.properties
,在其中添加以下參數(shù):
server.port=80 ## MULTIPART (MultipartProperties) # 開啟 multipart 上傳功能 spring.servlet.multipart.enabled=true # 文件寫入磁盤的閾值 spring.servlet.multipart.file-size-threshold=2KB # 最大文件大小 spring.servlet.multipart.max-file-size=200MB # 最大請求大小 spring.servlet.multipart.max-request-size=215MB ## 文件存儲所需參數(shù) # 所有通過 REST APIs 上傳的文件都將存儲在此目錄下 file.upload-dir=./uploads
其中file.upload-dir=./uploads
參數(shù)為自定義的參數(shù),創(chuàng)建FileProperties.java
POJO類,使配置參數(shù)可以自動綁定到POJO類。
import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "file") public class FileProperties { private String uploadDir; public String getUploadDir() { return uploadDir; } public void setUploadDir(String uploadDir) { this.uploadDir = uploadDir; } }
然后在@SpringBootApplication
注解的類中添加@EnableConfigurationProperties
注解以開啟ConfigurationProperties
功能。
SpringBootFileApplication.java
@SpringBootApplication @EnableConfigurationProperties({ FileProperties.class }) public class SpringBootFileApplication { public static void main(String[] args) { SpringApplication.run(SpringBootFileApplication.class, args); } }
配置完成,以后若有file
前綴開頭的參數(shù)需要配置,可直接在application.properties
配置文件中配置并更新FileProperties.java
即可。
另外再創(chuàng)建一個上傳文件成功之后的Response
響應實體類UploadFileResponse.java
及異常類FileException.java
來處理異常信息。
UploadFileResponse.java
public class UploadFileResponse { private String fileName; private String fileDownloadUri; private String fileType; private long size; public UploadFileResponse(String fileName, String fileDownloadUri, String fileType, long size) { this.fileName = fileName; this.fileDownloadUri = fileDownloadUri; this.fileType = fileType; this.size = size; } // getter and setter ... }
FileException.java
public class FileException extends RuntimeException{ public FileException(String message) { super(message); } public FileException(String message, Throwable cause) { super(message, cause); } }
創(chuàng)建接口
下面需要創(chuàng)建文件上傳下載所需的 REST APIs 接口。創(chuàng)建文件FileController.java
。
import com.james.sample.file.dto.UploadFileResponse; import com.james.sample.file.service.FileService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @RestController public class FileController { private static final Logger logger = LoggerFactory.getLogger(FileController.class); @Autowired private FileService fileService; @PostMapping("/uploadFile") public UploadFileResponse uploadFile(@RequestParam("file") MultipartFile file){ String fileName = fileService.storeFile(file); String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath() .path("/downloadFile/") .path(fileName) .toUriString(); return new UploadFileResponse(fileName, fileDownloadUri, file.getContentType(), file.getSize()); } @PostMapping("/uploadMultipleFiles") public ListuploadMultipleFiles(@RequestParam("files") MultipartFile[] files) { return Arrays.stream(files) .map(this::uploadFile) .collect(Collectors.toList()); } @GetMapping("/downloadFile/{fileName:.+}") public ResponseEntity downloadFile(@PathVariable String fileName, HttpServletRequest request) { // Load file as Resource Resource resource = fileService.loadFileAsResource(fileName); // Try to determine file's content type String contentType = null; try { contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath()); } catch (IOException ex) { logger.info("Could not determine file type."); } // Fallback to the default content type if type could not be determined if(contentType == null) { contentType = "application/octet-stream"; } return ResponseEntity.ok() .contentType(MediaType.parseMediaType(contentType)) .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"") .body(resource); } }
FileController
類在接收到用戶的請求后,使用FileService
類提供的storeFile()
方法將文件寫入到系統(tǒng)中進行存儲,其存儲目錄就是之前在application.properties
配置文件中的file.upload-dir
參數(shù)的值./uploads
。
下載接口downloadFile()
在接收到用戶請求之后,使用FileService
類提供的loadFileAsResource()
方法獲取存儲在系統(tǒng)中文件并返回文件供用戶下載。
FileService.java
import com.james.sample.file.exception.FileException; import com.james.sample.file.property.FileProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.net.MalformedURLException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; @Service public class FileService { private final Path fileStorageLocation; // 文件在本地存儲的地址 @Autowired public FileService(FileProperties fileProperties) { this.fileStorageLocation = Paths.get(fileProperties.getUploadDir()).toAbsolutePath().normalize(); try { Files.createDirectories(this.fileStorageLocation); } catch (Exception ex) { throw new FileException("Could not create the directory where the uploaded files will be stored.", ex); } } /** * 存儲文件到系統(tǒng) * * @param file 文件 * @return 文件名 */ public String storeFile(MultipartFile file) { // Normalize file name String fileName = StringUtils.cleanPath(file.getOriginalFilename()); try { // Check if the file's name contains invalid characters if(fileName.contains("..")) { throw new FileException("Sorry! Filename contains invalid path sequence " + fileName); } // Copy file to the target location (Replacing existing file with the same name) Path targetLocation = this.fileStorageLocation.resolve(fileName); Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING); return fileName; } catch (IOException ex) { throw new FileException("Could not store file " + fileName + ". Please try again!", ex); } } /** * 加載文件 * @param fileName 文件名 * @return 文件 */ public Resource loadFileAsResource(String fileName) { try { Path filePath = this.fileStorageLocation.resolve(fileName).normalize(); Resource resource = new UrlResource(filePath.toUri()); if(resource.exists()) { return resource; } else { throw new FileException("File not found " + fileName); } } catch (MalformedURLException ex) { throw new FileException("File not found " + fileName, ex); } } }
接口測試
在完成上述的代碼之后,打開SpringBootFileApplication.java
并運行,運行完成之后就可以使用 Postman 進行測試了。
單個文件上傳結(jié)果:
多個文件上傳結(jié)果:
Web 前端開發(fā)
index.html
Spring Boot File Upload / Download Rest API Example Spring Boot File Upload / Download Rest API Example
Upload Single File
Upload Multiple Files
main.css
* { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } body { margin: 0; padding: 0; font-weight: 400; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 1rem; line-height: 1.58; color: #333; background-color: #f4f4f4; } body:before { height: 50%; width: 100%; position: absolute; top: 0; left: 0; background: #128ff2; content: ""; z-index: 0; } .clearfix:after { display: block; content: ""; clear: both; } h2, h3, h4, h5, h6, h7 { margin-top: 20px; margin-bottom: 20px; } h2 { font-size: 1.7em; } a { color: #128ff2; } button { box-shadow: none; border: 1px solid transparent; font-size: 14px; outline: none; line-height: 100%; white-space: nowrap; vertical-align: middle; padding: 0.6rem 1rem; border-radius: 2px; transition: all 0.2s ease-in-out; cursor: pointer; min-height: 38px; } button.primary { background-color: #128ff2; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.12); color: #fff; } input { font-size: 1rem; } input[type="file"] { border: 1px solid #128ff2; padding: 6px; max-width: 100%; } .file-input { width: 100%; } .submit-btn { display: block; margin-top: 15px; min-width: 100px; } @media screen and (min-width: 500px) { .file-input { width: calc(100% - 115px); } .submit-btn { display: inline-block; margin-top: 0; margin-left: 10px; } } .upload-container { max-width: 700px; margin-left: auto; margin-right: auto; background-color: #fff; box-shadow: 0 1px 11px rgba(0, 0, 0, 0.27); margin-top: 60px; min-height: 400px; position: relative; padding: 20px; } .upload-header { border-bottom: 1px solid #ececec; } .upload-header h3 { font-weight: 500; } .single-upload { padding-bottom: 20px; margin-bottom: 20px; border-bottom: 1px solid #e8e8e8; } .upload-response { overflow-x: hidden; word-break: break-all; }
main.js
'use strict'; var singleUploadForm = document.querySelector('#singleUploadForm'); var singleFileUploadInput = document.querySelector('#singleFileUploadInput'); var singleFileUploadError = document.querySelector('#singleFileUploadError'); var singleFileUploadSuccess = document.querySelector('#singleFileUploadSuccess'); var multipleUploadForm = document.querySelector('#multipleUploadForm'); var multipleFileUploadInput = document.querySelector('#multipleFileUploadInput'); var multipleFileUploadError = document.querySelector('#multipleFileUploadError'); var multipleFileUploadSuccess = document.querySelector('#multipleFileUploadSuccess'); function uploadSingleFile(file) { var formData = new FormData(); formData.append("file", file); var xhr = new XMLHttpRequest(); xhr.open("POST", "/uploadFile"); xhr.onload = function() { console.log(xhr.responseText); var response = JSON.parse(xhr.responseText); if(xhr.status == 200) { singleFileUploadError.style.display = "none"; singleFileUploadSuccess.innerHTML = "File Uploaded Successfully.
DownloadUrl : " + response.fileDownloadUri + "
"; singleFileUploadSuccess.style.display = "block"; } else { singleFileUploadSuccess.style.display = "none"; singleFileUploadError.innerHTML = (response && response.message) || "Some Error Occurred"; } } xhr.send(formData); } function uploadMultipleFiles(files) { var formData = new FormData(); for(var index = 0; index < files.length; index++) { formData.append("files", files[index]); } var xhr = new XMLHttpRequest(); xhr.open("POST", "/uploadMultipleFiles"); xhr.onload = function() { console.log(xhr.responseText); var response = JSON.parse(xhr.responseText); if(xhr.status == 200) { multipleFileUploadError.style.display = "none"; var content = "All Files Uploaded Successfully
"; for(var i = 0; i < response.length; i++) { content += "DownloadUrl : " + response[i].fileDownloadUri + "
"; } multipleFileUploadSuccess.innerHTML = content; multipleFileUploadSuccess.style.display = "block"; } else { multipleFileUploadSuccess.style.display = "none"; multipleFileUploadError.innerHTML = (response && response.message) || "Some Error Occurred"; } } xhr.send(formData); } singleUploadForm.addEventListener('submit', function(event){ var files = singleFileUploadInput.files; if(files.length === 0) { singleFileUploadError.innerHTML = "Please select a file"; singleFileUploadError.style.display = "block"; } uploadSingleFile(files[0]); event.preventDefault(); }, true); multipleUploadForm.addEventListener('submit', function(event){ var files = multipleFileUploadInput.files; if(files.length === 0) { multipleFileUploadError.innerHTML = "Please select at least one file"; multipleFileUploadError.style.display = "block"; } uploadMultipleFiles(files); event.preventDefault(); }, true);
關于Spring Boot 文件上傳與下載就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。