檔案上傳和下載
阿新 • • 發佈:2020-11-18
application.properties
## 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 ## 檔案儲存所需引數 # 所有通過 REST APIs 上傳的檔案都將儲存在此目錄下 file.uploadDir=C:\\Users\\Yuri\\Desktop\\TRY
FileService
package yuri.newfile.demo.service; import org.springframework.core.io.UrlResource; import org.springframework.util.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import yuri.newfile.demo.pojo.FileProperties; import yuri.newfile.demo.util.FileException; import org.springframework.core.io.Resource; 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 e) { throw new FileException("不能建立上傳檔案儲存路徑"); } } public String storeFile(MultipartFile file) { // file.getOriginalFilename()返回檔名,但某些瀏覽器下會返回帶碟符的路徑,所以用StringUtils.cleanPath()進行處理 String fileName = StringUtils.cleanPath(file.getOriginalFilename()); try{ // 檢查檔名是否含有非法字元 if (fileName.contains("..")){ throw new FileException("檔名含有非法字元"); } // resolve()把儲存路徑fileStorageLocation和檔名fileName合併為一條路徑 // C:\Users\Yuri\Desktop\TRY+xxx = C:\Users\Yuri\Desktop\TRY\xxx Path path = this.fileStorageLocation.resolve(fileName); // 對檔案進行儲存操作,三個引數分別是輸入流、路徑、(列舉)操作引數 Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING); return fileName; }catch (IOException e){ throw new FileException("不能儲存檔案:" + fileName); } } public Resource loadFileAsResource(String fileName) { try{ Path filePath = this.fileStorageLocation.resolve(fileName).normalize(); Resource resource = new UrlResource(filePath.toUri()); // System.out.println(filePath); // System.out.println(filePath.toUri()); // System.out.println(resource); if(resource.exists()){ return resource; }else{ throw new FileException("未找到檔案:" + fileName); } } catch (MalformedURLException e) { throw new FileException("未找到檔案:" + fileName, e); } } }
FileController
package yuri.newfile.demo.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.servlet.ModelAndView; import yuri.newfile.demo.service.FileService; import yuri.newfile.demo.util.UploadFileResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.naming.Context; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import static org.springframework.web.servlet.function.RequestPredicates.contentType; @RestController public class FileController { private static final Logger logger = LoggerFactory.getLogger(FileController.class); @Autowired private FileService fileService; @PostMapping("/uploadFile") public UploadFileResponse uploadFileResponse(@RequestParam("file")MultipartFile file){ // 對檔案進行儲存操作 String fileName = fileService.storeFile(file); // 對返回引數進行設定 // ServletUriComponentsBuilder構建Url地址, // fromCurrentContextPath()為本機IP,比如http://localhost:8080 // path是對後續路徑進行增添 // toUrlString是進行Url地址轉義,因為起初構建的並不是標準url地址 String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath() .path("/downloadFile/") .path(fileName) .toUriString(); // 返回此次傳輸的UploadFileResponse物件 return new UploadFileResponse(fileName, fileDownloadUri, file.getContentType(), file.getSize()); } @PostMapping("/uploadFiles") public List<UploadFileResponse> uploadFileResponses(@RequestParam("files") MultipartFile[] files){ // Java8新特性:Stream()將陣列轉換為流,map()是過濾操作,此處過濾方法為uploadFileResponse,collect(Collectors.toList())是固定寫法,將結果轉為List return Arrays.stream(files) .map(this::uploadFileResponse) .collect(Collectors.toList()); } @GetMapping("/downloadFile/{fileName:.+}") // @PathVariable可以把url{}中變數賦值給引數,當不寫value就對應名字自動賦值 public ResponseEntity<Resource> downloadFile(@PathVariable String fileName, HttpServletRequest request){ Resource resource = fileService.loadFileAsResource(fileName); String contentType = null; try{ // getMimeType()獲取檔案的格式,是ServletContext的一個方法 contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath()); } catch (IOException e){ logger.info("不能確定檔案型別"); } if (contentType == null) { contentType = "application/octet-stream"; } // 進行檔案下載處理 return ResponseEntity.ok() .contentType(MediaType.parseMediaType(contentType)) .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" +resource.getFilename() + "\"") .body(resource); } }