1.实现文件存储功能(直接写成业务方法,方便后续使用)
package com.smartbird.clouddisk.service;
import com.smartbird.clouddisk.common.exception.BusException;
import com.smartbird.clouddisk.config.StorageProperties;
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.FileSystemUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@Service
public class StorageService {
private final Path rootLocation;
@Autowired
public StorageService(StorageProperties properties) {
this.rootLocation = Paths.get(properties.getLocation());
}public void init() {
try {
Files.createDirectories(rootLocation);
}
catch (IOException e) {
throw new BusException("Could not initialize storage");
}
}/**
* @Author: kech
* @Description: 存入
* @Date: 2021/12/31
*/
public String store(MultipartFile file) {
try {
if (file.isEmpty()) {
throw new BusException("Failed to store empty file.");
}
//子文件夹用uuid命名
String uuidName = UUID.randomUUID().toString();
File dir = new File(rootLocation.toString()+"/"+uuidName);
dir.mkdir();
Path destinationFile = this.rootLocation.resolve(dir.getAbsolutePath()+"/"+file.getOriginalFilename())
.normalize().toAbsolutePath();
try (InputStream inputStream = file.getInputStream()) {
Files.copy(inputStream, destinationFile,
StandardCopyOption.REPLACE_EXISTING);
return uuidName+"/"+file.getOriginalFilename();
}
}
catch (IOException e) {
throw new BusException("Failed to store file.");
}
}/**
* @Author: kech
* @Description:遍历本地文件夹
* @Date: 2021/12/31
*/
public List loadAll() {
try {
List res = new ArrayList<>();
File file = new File("./"+this.rootLocation.getFileName());
if(null != file && file.isDirectory()){
File[] fs=file.listFiles();
for(File f: fs){
if(!f.isDirectory())
res.add(f.getName());
}
}
return res;
}
catch (Exception e) {
throw new BusException("Failed to read stored files");
}
}public Path load(String filename) {
return rootLocation.resolve(filename);
}public Resource loadAsResource(String filename) {
try {
Path file = load(filename);
Resource resource = new UrlResource(file.toUri());
if (resource.exists() || resource.isReadable()) {
return resource;
}
else {
throw new BusException(
"Could not read file: " + filename);
}
}
catch (MalformedURLException e) {
throw new BusException("Could not read file: " + filename);
}
}public void deleteAll() {
FileSystemUtils.deleteRecursively(rootLocation.toFile());
}
}
2.控制类方法实现(主要实现普通文件的上传,图片文件上传,图片实时预览,视频上传,视频预览等功能)
package com.smartbird.clouddisk.controller;
import com.smartbird.clouddisk.common.dto.UpLoadDto;
import com.smartbird.clouddisk.common.exception.BusException;
import com.smartbird.clouddisk.common.handler.NonStaticResourceHttpRequestHandler;
import com.smartbird.clouddisk.common.model.R;
import com.smartbird.clouddisk.common.util.SecurityUtils;
import com.smartbird.clouddisk.common.util.StringUtils;
import com.smartbird.clouddisk.common.vo.PersonInfoVo;
import com.smartbird.clouddisk.config.ServerConfig;
import com.smartbird.clouddisk.config.StorageProperties;
import com.smartbird.clouddisk.entity.User;
import com.smartbird.clouddisk.service.StorageService;
import com.smartbird.clouddisk.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
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.util.UriUtils;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@RestController
@Api(value = "https://www.it610.com/article/文件上传")
public class StorageController {
@Autowired
private StorageService storageService;
@Autowired
private ServerConfig serverConfig;
@Autowired
private StorageProperties storageProperties;
@Autowired
private UserService userService;
@Autowired
private NonStaticResourceHttpRequestHandler nonStaticResourceHttpRequestHandler;
@GetMapping("/download/{dirName:.+}/{fileName:.+}")
@ApiOperation(value = "https://www.it610.com/article/根据文件名从下载文件")
public ResponseEntity serveFile(@PathVariable String dirName,
@PathVariable String fileName) throws IOException {
if(StringUtils.isEmpty(fileName)) throw new BusException("查找文件名字为空");
FileInputStream fi = new FileInputStream("./"+storageProperties.getLocation()+"/"+dirName+"/"+fileName);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf("application/download"));
headers.set("Content-Disposition", "attachment;
fileName*=UTF-8''" + UriUtils.encode(fileName, "UTF-8"));
return new ResponseEntity(IOUtils.toByteArray(fi), headers, HttpStatus.OK);
}/**
* @Author: kech
* @Description: 将前端文件保存到服务器本地
* @Date: 2021/12/31
* @return
*/
@PostMapping("/upload")
@ApiOperation(value = "https://www.it610.com/article/上传文件")
public R handleFileUpload(HttpServletRequest request, @RequestPart("file") MultipartFile file) throws Exception {
if(null == file) throw new BusException("上传空文件");
String storePath = storageService.store(file);
UpLoadDto upLoadDto = new UpLoadDto();
upLoadDto.setRelativePath("/download/"+storePath);
//upLoadDto.setUrlPath(serverConfig.getUrl()+"/download/"+storePath);
upLoadDto.setUrlPath("http://"+request.getServerName()+":"+request.getServerPort()+"/download/"+storePath);
return new R().Success(upLoadDto);
}@PostMapping("/api/upload-video")
@ApiOperation(value = "https://www.it610.com/article/上传视频")
public R uploadVideo(HttpServletRequest request, @RequestPart("file") MultipartFile file) throws Exception {
if(null == file) throw new BusException("上传空文件");
String storePath = storageService.store(file);
UpLoadDto upLoadDto = new UpLoadDto();
upLoadDto.setRelativePath("/video/"+storePath);
//upLoadDto.setUrlPath(serverConfig.getUrl()+"/download/"+storePath);
upLoadDto.setUrlPath("http://"+request.getServerName()+":"+request.getServerPort()+"/video/"+storePath);
return new R().Success(upLoadDto);
}//@GetMapping("/video/{dirName:.+}/{fileName:.+}")
//@ApiOperation(value = "https://www.it610.com/article/根据文件名从下载视频")
//public ResponseEntity downloadVideo(@PathVariable String dirName,
//@PathVariable String fileName) throws IOException {
//if(StringUtils.isEmpty(fileName)) throw new BusException("查找文件名字为空");
//FileInputStream fi = new FileInputStream("./"+storageProperties.getLocation()+"/"+dirName+"/"+fileName);
//HttpHeaders headers = new HttpHeaders();
//headers.setContentType(MediaType.valueOf("application/download"));
//headers.set("Content-Disposition", "attachment;
fileName*=UTF-8''" + UriUtils.encode(fileName, "UTF-8"));
//return new ResponseEntity(IOUtils.toByteArray(fi), headers, HttpStatus.OK);
//}/**
* 预览视频文件, 支持 byte-range 请求
*/
@GetMapping("/video/{dirName:.+}/{fileName:.+}")
public void videoPreview(@PathVariable String dirName,
@PathVariable String fileName, HttpServletRequest request, HttpServletResponse response) throws Exception {
String path = "./"+storageProperties.getLocation()+"/"+dirName+"/"+fileName;
Path filePath = Paths.get(path);
if (Files.exists(filePath)) {
String mimeType = Files.probeContentType(filePath);
if (!StringUtils.isEmpty(mimeType)) {
response.setContentType(mimeType);
}
request.setAttribute(NonStaticResourceHttpRequestHandler.ATTR_FILE, filePath);
nonStaticResourceHttpRequestHandler.handleRequest(request, response);
} else {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
}
}@PostMapping("/uploadPreview")
@ApiOperation(value = "https://www.it610.com/article/上传预览文件")
public R uploadPreviewFile(HttpServletRequest request, @RequestPart("file") MultipartFile file) {
if(null == file) throw new BusException("上传空文件");
String storePath = storageService.store(file);
UpLoadDto upLoadDto = new UpLoadDto();
upLoadDto.setRelativePath("/preview/"+storePath);
//upLoadDto.setUrlPath(serverConfig.getUrl()+"/download/"+storePath);
upLoadDto.setUrlPath("http://"+request.getServerName()+":"+request.getServerPort()+"/preview/"+storePath);
//PersonInfoVo personInfoVo = new PersonInfoVo();
//User user= SecurityUtils.getLoginUser().getUser();
//personInfoVo.setUserId(user.getUserId());
//personInfoVo.setAvatar("http://"+request.getServerName()+":"+request.getServerPort()+"/preview/"+storePath);
//userService.UpdatePersonInfo(personInfoVo);
return new R().Success(upLoadDto);
}@GetMapping("/preview/{dirName:.+}/{fileName:.+}")
@ApiOperation(value = "https://www.it610.com/article/根据文件名实现预览功能")
public void previewFile(@PathVariable String dirName,
@PathVariable String fileName, HttpServletResponse response) throws IOException {
showImg("./"+storageProperties.getLocation()+"/"+dirName+"/"+fileName, response);
}public static void showImg(String path, HttpServletResponse response){
if(path!=null&&!path.equals("")){try {
FileInputStream fis = new FileInputStream(path);
ServletOutputStream os = response.getOutputStream();
byte [] b = new byte[1024*8];
while(fis.read(b)!=-1){
os.write(b);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.访问接口测试(使用postman进行测试) 【后端开发|Springboot实现上传文件以及文件实时预览(包括图片预览,视频预览)】测试视频上传保存至服务器,它会返回一个Url地址。

文章图片
测试实时预览视频的功能

文章图片
推荐阅读
- JVM|JVM--基础--20--对象的创建过程
- java|spring Security配置拦截规则
- 笔记|JavaSE基础语法--傻瓜笔记--1009(第二章:IDE的使用——标识符)
- 06_Springboot|Spring AOP 介绍与简单日志切面实现
- 蓝桥杯练习|试题 算法训练 台阶问题
- Spring源码逻辑|Spring01 -- 启动和扫描逻辑模拟
- JAVA基础|Lambda从入门到精通(一篇搞懂)
- Java学习日记|Java学习日记14——Lambda表达式以及一些高级语法
- android|初学Android网络封装