如何基于SpringWeb?MultipartFile實現(xiàn)文件上傳、下載功能
前言
在Web開發(fā)中,文件上傳是一個常見的功能需求。Spring框架提供了MultipartFile接口,用于處理文件上傳請求。MultipartFile可以代表一個多部分文件上傳請求中的一個文件,提供了一系列方法用于獲取文件的各種屬性和內(nèi)容,使得在后端處理文件上傳變得十分方便。下面我們將介紹MultipartFile在Web應用中的幾種常見使用場景。
1. 圖片上傳
在Web應用中,圖片上傳是一種常見的場景。用戶需要上傳頭像、相片、證件照等圖片文件,而后端需要接收并保存這些文件。使用MultipartFile接口可以輕松地實現(xiàn)圖片文件的接收和處理。通過獲取文件的原始文件名、內(nèi)容類型、大小等屬性,我們可以實現(xiàn)對圖片文件的有效管理和存儲。例如,我們可以將圖片文件保存到服務器的文件系統(tǒng)中,或者將其存儲到云存儲服務中。
2. 文件下載
除了文件上傳,文件下載也是Web應用中常見的功能需求。使用MultipartFile接口,我們可以實現(xiàn)文件的下載功能。在服務器端,我們可以將文件作為MultipartFile對象進行處理,并通過設置響應頭信息,將文件作為下載內(nèi)容返回給客戶端??蛻舳私邮盏轿募螅梢詫⑵浔4娴奖镜卮疟P或進行其他處理。
3. 文件編輯
在Web應用中,有時候用戶需要對上傳的文件進行編輯操作,例如修改文件名、修改文件內(nèi)容等。使用MultipartFile接口,我們可以實現(xiàn)對文件的編輯功能。首先,我們可以通過MultipartFile接口獲取上傳的文件對象,然后對其進行相應的編輯操作。例如,我們可以修改文件的名稱、修改文件的內(nèi)容等。編輯完成后,我們可以將修改后的文件保存到服務器或返回給客戶端。
4. 文件預覽和展示
在Web應用中,有時候我們需要將上傳的文件進行預覽或展示。例如,在文檔管理系統(tǒng)中,用戶需要預覽或下載文檔文件。使用MultipartFile接口,我們可以實現(xiàn)文件的預覽和展示功能。我們可以將文件作為MultipartFile對象進行處理,然后將其內(nèi)容轉換為適當?shù)母袷竭M行展示。例如,對于PDF文件,我們可以使用PDF閱讀器插件進行展示;對于圖片文件,我們可以將其直接展示在網(wǎng)頁上。
5. 文件批量上傳和處理
在實際應用中,有時候用戶需要批量上傳多個文件,并對這些文件進行處理。使用MultipartFile接口,我們可以實現(xiàn)文件的批量上傳和處理功能。我們可以將多個文件作為一個多部分文件上傳請求進行處理,然后對每個文件進行相應的操作。例如,我們可以將多個圖片文件批量上傳到服務器,并對它們進行壓縮、裁剪等處理。
代碼
package com.javagpt.back.controller;
import com.javagpt.application.context.UserAppContextHolder;
import com.javagpt.application.file.FileApplicationService;
import com.javagpt.application.file.FileDTO;
import com.javagpt.common.annotation.RespSuccess;
import com.javagpt.common.constant.EMConstant;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@Api(tags = "文件接口")
@Slf4j
@RestController
@RequestMapping(EMConstant.API_V1 + "/file")
@RespSuccess
@RequiredArgsConstructor
public class FileController {
private final FileApplicationService fileApplicationService;
@ApiOperation("通用文件上傳")
@PostMapping(value = "/uploadFile")
public FileDTO uploadFile(@RequestParam("file") MultipartFile multipartFile) throws IOException {
Long enterpriseId = UserAppContextHolder.getCurrentUser().getEnterpriseId();
FileDTO fileDTO = fileApplicationService.saveFile(enterpriseId, multipartFile);
return fileDTO;
}
//@PreAuthorize("hasAuthority('mp:file:download')")
@ApiOperation("下載文件")
@GetMapping(value = "/downloadFile")
public void download(@RequestParam(value = "id") Long id, HttpServletResponse response) throws IOException {
fileApplicationService.downloadFile(response, id, UserAppContextHolder.getCurrentUser().getEnterpriseId());
}
@ApiOperation("查看文件信息")
@GetMapping(value = "/info")
public FileDTO fileInfo(@RequestParam(value = "id") Long id) throws IOException {
return fileApplicationService.findById(id);
}
@ApiOperation("下載視頻")
@GetMapping(value = "/downloadFile2")
public void download2(@RequestParam(value = "id") Long id, HttpServletRequest request, HttpServletResponse response) throws IOException {
fileApplicationService.downloadVideo(request, response, id, UserAppContextHolder.getCurrentUser().getEnterpriseId());
}
}package com.javagpt.application.file;
import com.javagpt.common.exception.BusinessRuntimeException;
import com.javagpt.common.oos.OssService;
import com.javagpt.common.util.ModelUtils;
import com.javagpt.common.util.SpringResponseUtils;
import com.javagpt.file.entity.FileEntity;
import com.javagpt.file.repository.FileRepository;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
@Service
@Slf4j
@RequiredArgsConstructor
public class FileApplicationService {
private final OssService ossService;
private final FileRepository fileRepository;
public FileDTO findById(Long id) {
FileEntity fileEntity = fileRepository.findById(id);
return ModelUtils.convert(fileEntity, FileDTO.class);
}
@Transactional
public FileDTO saveFile(Long enterpriseId, MultipartFile file) {
FileEntity fileEntity = saveFile(enterpriseId, file, null);
return ModelUtils.convert(fileEntity, FileDTO.class);
}
@Transactional
public FileEntity saveFile(Long enterpriseId, MultipartFile file, String fileName) {
String originalFilename = file.getOriginalFilename();
String name = StringUtils.isBlank(fileName) ? FilenameUtils.getBaseName(originalFilename) : fileName;
String suffix = FilenameUtils.getExtension(originalFilename);
long size = file.getSize();
FileEntity fileEntity = new FileEntity();
fileEntity.setName(name).setSuffix(suffix).setSize(size).setEnterpriseId(enterpriseId);
fileEntity = fileEntity.save();
String key = fileEntity.getPath();
InputStream inputStream = null;
try {
inputStream = file.getInputStream();
} catch (IOException e) {
log.error("saveFile error:", e);
throw BusinessRuntimeException.error("上傳文件失敗");
}
ossService.uploadFile(inputStream, key);
IOUtils.closeQuietly(inputStream);
return fileEntity;
}
@Transactional
public FileEntity saveFile(File file) {
long size = file.length();
FileEntity fileEntity = new FileEntity();
String baseName = FilenameUtils.getBaseName(file.getName());
String extension = FilenameUtils.getExtension(file.getName());
fileEntity.setName(baseName).setSuffix(extension).setSize(size);
fileEntity = fileEntity.save();
String key = fileEntity.getPath();
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
ossService.uploadFile(inputStream, key);
} catch (FileNotFoundException e) {
log.error("saveFile error:", e);
throw BusinessRuntimeException.error("上傳文件失敗");
}
IOUtils.closeQuietly(inputStream);
return fileEntity;
}
public void downloadFile(HttpServletResponse response, Long fileId, Long enterpriseId) throws IOException {
FileEntity fileEntity = fileRepository.findById(fileId);
if (fileEntity == null) {
throw BusinessRuntimeException.error("無效的文件Id");
}
String key = fileEntity.getPath();
InputStream inputStream = ossService.downloadFile(key);
SpringResponseUtils.writeAndFlushResponse(inputStream, response, fileEntity.fileFullName());
}
public void downloadVideo(HttpServletRequest request, HttpServletResponse response, Long fileId, Long enterpriseId) throws IOException {
FileEntity fileEntity = fileRepository.findById(fileId);
if (fileEntity == null) {
throw BusinessRuntimeException.error("無效的文件Id");
}
response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
Long fileSize = fileEntity.getSize();
long start = 0, end = fileSize - 1;
//判斷前端需不需要分片下載
if (StringUtils.isNotBlank(request.getHeader("Range"))) {
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
String numRange = request.getHeader("Range").replaceAll("bytes=", "");
String[] strRange = numRange.split("-");
if (strRange.length == 2) {
start = Long.parseLong(strRange[0].trim());
end = Long.parseLong(strRange[1].trim());
//若結束字節(jié)超出文件大小 取文件大小
if (end > fileSize - 1) {
end = fileSize - 1;
}
} else {
//若只給一個長度 開始位置一直到結束
start = Long.parseLong(numRange.replaceAll("-", "").trim());
}
}
long rangeLength = end - start + 1;
String contentRange = new StringBuffer("bytes ").append(start).append("-").append(end).append("/").append(fileSize).toString();
response.setHeader(HttpHeaders.CONTENT_RANGE, contentRange);
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(rangeLength));
String key = fileEntity.getPath();
InputStream inputStream = ossService.downloadFile2(key, start, end);
SpringResponseUtils.writeAndFlushResponse(inputStream, response, fileEntity.fileFullName());
}
}總之,MultipartFile接口在Web應用中具有廣泛的應用場景,可以實現(xiàn)文件上傳、下載、編輯、預覽和批量處理等功能。通過熟練掌握MultipartFile接口的使用方法和技巧,我們可以更加高效地處理文件上傳和下載請求,提升Web應用的用戶體驗和功能性能。
總結
到此這篇關于如何基于SpringWeb MultipartFile實現(xiàn)文件上傳、下載功能的文章就介紹到這了,更多相關SpringWeb MultipartFile文件上傳下載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
詳解SpringMVC?HandlerInterceptor攔截器的使用與參數(shù)
本文主要介紹了詳解SpringMVC?HandlerInterceptor攔截器的使用與參數(shù),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01
ZooKeeper入門教程三分布式鎖實現(xiàn)及完整運行源碼
本文是ZooKeeper入門系列教程,分布式鎖有多種實現(xiàn)方式,比如通過數(shù)據(jù)庫、redis都可實現(xiàn)。作為分布式協(xié)同工具ZooKeeper,當然也有著標準的實現(xiàn)方式。本文介紹在zookeeper中如何實現(xiàn)排他鎖2022-01-01
如何在SpringBoot項目里進行統(tǒng)一異常處理
這篇文章主要介紹了如何在SpringBoot項目里進行統(tǒng)一異常處理,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值。需要的小伙伴可以參考一下2022-07-07
SpringBoot3整合pageHelper實現(xiàn)分頁功能
PageHelper是一個開源的Java分頁插件,它提供了方便的分頁查詢功能,適用于大多數(shù)基于Java的持久層框架(如MyBatis、Hibernate等),本文給大家介紹了springboot3整合pageHelper實現(xiàn)分頁功能的方法,需要的朋友可以參考下2024-08-08
SpringBoot獲取application.properties文件中文亂碼問題及解決
這篇文章主要介紹了SpringBoot獲取application.properties文件中文亂碼問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05
Spring Boot不同版本Redis設置JedisConnectionFactory詳解
本文章向大家介紹Spring Boot不同版本Redis設置JedisConnectionFactory,主要內(nèi)容包括1.X 版本、2.X 版本、2.、基本概念、基礎應用、原理機制和需要注意的事項等,并結合實例形式分析了其使用技巧,希望通過本文能幫助到大家理解應用這部分內(nèi)容2023-09-09
Spring Data JPA結合Mybatis進行分頁查詢的實現(xiàn)
本文主要介紹了Spring Data JPA結合Mybatis進行分頁查詢的實現(xiàn)2024-03-03

