后端开发|Springboot实现上传文件以及文件实时预览(包括图片预览,视频预览)

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地址。
后端开发|Springboot实现上传文件以及文件实时预览(包括图片预览,视频预览)
文章图片

测试实时预览视频的功能
后端开发|Springboot实现上传文件以及文件实时预览(包括图片预览,视频预览)
文章图片

    推荐阅读