package com.izouma.nineth.web; import com.izouma.nineth.domain.FileObject; import com.izouma.nineth.exception.BusinessException; import com.izouma.nineth.service.storage.StorageService; import com.izouma.nineth.utils.ImageUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.apache.poi.util.TempFile; import org.bytedeco.javacv.FFmpegFrameGrabber; import org.bytedeco.javacv.Frame; import org.bytedeco.javacv.Java2DFrameConverter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.*; import java.net.URLConnection; import java.text.SimpleDateFormat; import java.util.*; import java.util.regex.Pattern; @RestController @RequestMapping("/upload") @Slf4j public class FileUploadController { @Autowired private StorageService storageService; @PostMapping("/file") public String uploadFile(@RequestParam("file") MultipartFile file, @RequestParam(value = "path", required = false) String path, @RequestParam(value = "compress", defaultValue = "false") boolean compress, @RequestParam(value = "width", required = false) Integer width, @RequestParam(value = "height", required = false) Integer height) throws IOException { String ext = Optional.ofNullable(FilenameUtils.getExtension(file.getOriginalFilename())).orElse("") .toLowerCase().replace("jpeg", "jpg"); if (path == null) { String basePath = Optional.ofNullable(file.getContentType()).orElse("application").split("/")[0]; path = basePath + "/" + new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + RandomStringUtils.randomAlphabetic(8) + "." + ext; } if (Pattern.matches("(jpg|png)", ext) && (compress || width != null || height != null)) { if (width == null && height == null) { width = Integer.MAX_VALUE; height = Integer.MAX_VALUE; } else if (height == null) { height = Integer.MAX_VALUE; } else if (width == null) { width = Integer.MAX_VALUE; } BufferedImage img = null; if ("jpg".equals(ext)) { img = ImageUtils.resizeJpg(file.getInputStream(), width, height, compress); } else if ("png".equals(ext)) { img = ImageUtils.resizePng(file.getInputStream(), width, height, compress); } Objects.requireNonNull(img, "图片压缩失败"); ByteArrayOutputStream os = new ByteArrayOutputStream(); ImageIO.write(img, ext, os); InputStream is = new ByteArrayInputStream(os.toByteArray()); return storageService.uploadFromInputStream(is, path); } return storageService.uploadFromInputStream(file.getInputStream(), path); } @PostMapping("/base64") public String uploadImage(@RequestParam("base64") String base64, @RequestParam(value = "path", required = false) String path) { base64 = base64.substring(base64.indexOf(',') + 1); Base64.Decoder decoder = Base64.getDecoder(); if (path == null) { String ext = ".jpg"; try { InputStream is = new ByteArrayInputStream(decoder.decode(base64.getBytes())); String type = URLConnection.guessContentTypeFromStream(is); ext = type.replace("image/", ".").replace("jpeg", "jpg"); } catch (Exception ignored) { } path = "image/" + new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + RandomStringUtils.randomAlphabetic(8) + ext; } InputStream is; try { is = new ByteArrayInputStream(decoder.decode(base64.getBytes())); } catch (Exception e) { log.error("上传失败", e); throw new BusinessException("上传失败", e.getMessage()); } return storageService.uploadFromInputStream(is, path); } @PostMapping("/fileObject") public FileObject uploadFileObject(@RequestParam("file") MultipartFile file, @RequestParam(value = "compress", defaultValue = "false") boolean compress, @RequestParam(value = "width", required = false) Integer width, @RequestParam(value = "height", required = false) Integer height) throws IOException { String ext = Optional.ofNullable(FilenameUtils.getExtension(file.getOriginalFilename())).orElse("") .toLowerCase().replace("jpeg", "jpg"); String[] extList = new String[]{"jpg", "jpeg", "png", "gif", "mp4"}; if (!ArrayUtils.contains(extList, ext.toLowerCase())) { throw new BusinessException("仅支持" + StringUtils.join(extList, "、") + "格式"); } File tmpFile = File.createTempFile("upload_", "." + ext); FileUtils.copyToFile(file.getInputStream(), tmpFile); String path = "nft/" + new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + RandomStringUtils.randomAlphabetic(8) + "." + ext; String url; if (Pattern.matches("(jpg|png)", ext) && (compress || width != null || height != null)) { if (width == null && height == null) { width = Integer.MAX_VALUE; height = Integer.MAX_VALUE; } else if (height == null) { height = Integer.MAX_VALUE; } else if (width == null) { width = Integer.MAX_VALUE; } BufferedImage img; if ("jpg".equals(ext)) { img = ImageUtils.resizeJpg(new FileInputStream(tmpFile), width, height, compress); } else { img = ImageUtils.resizePng(new FileInputStream(tmpFile), width, height, compress); } ByteArrayOutputStream os = new ByteArrayOutputStream(); ImageIO.write(img, ext, os); InputStream is = new ByteArrayInputStream(os.toByteArray()); url = storageService.uploadFromInputStream(is, path); } else { url = storageService.uploadFromInputStream(new FileInputStream(tmpFile), path); } String thumbUrl = null; if ("mp4".equalsIgnoreCase(ext)) { String thumbPath = "thumb_image/" + new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + RandomStringUtils.randomAlphabetic(8) + ".jpg"; FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(tmpFile); Java2DFrameConverter frameConverter = new Java2DFrameConverter(); try { frameGrabber.start(); Frame frame = null; while (frame == null) { frame = frameGrabber.grabKeyFrame(); } Objects.requireNonNull(frame, "获取视频缩略图失败"); BufferedImage thumbBi = frameConverter.convert(frame); BufferedImage thumbResized = ImageUtils.resizeJpg(thumbBi, 1000, 1000, false); ByteArrayOutputStream os = new ByteArrayOutputStream(); ImageIO.write(thumbResized, "jpg", os); InputStream is = new ByteArrayInputStream(os.toByteArray()); thumbUrl = storageService.uploadFromInputStream(is, thumbPath); } catch (Exception e) { e.printStackTrace(); } finally { frameGrabber.stop(); } } return new FileObject(file.getOriginalFilename(), url, thumbUrl, file.getContentType()); } @PostMapping("/3dModel") public FileObject upload3dModel(@RequestParam("file") MultipartFile file) throws IOException { if (!"zip".equalsIgnoreCase(FilenameUtils.getExtension(file.getOriginalFilename()))) { throw new BusinessException("只能上传zip"); } File destDir = TempFile.createTempDirectory(RandomStringUtils.randomAlphabetic(20)); com.izouma.nineth.utils.FileUtils.unzip(file.getInputStream(), destDir); File fbxFile = com.izouma.nineth.utils.FileUtils.findInDir(destDir, ".fbx"); if (fbxFile == null) { throw new BusinessException("找不到fbx文件"); } File fbxDir = fbxFile.getParentFile(); String basePath = "fbx/" + new SimpleDateFormat("yyyy-MM_dd-HH").format(new Date()) + "/" + RandomStringUtils.randomAlphabetic(16); List urls = new ArrayList<>(); for (File listFile : fbxDir.listFiles()) { if (!listFile.isHidden() && !listFile.isDirectory()) { urls.add(storageService.uploadFromInputStream(new FileInputStream(listFile), basePath + "/" + listFile.getName())); } } String fbxUrl = urls.stream().filter(s -> s.toLowerCase().endsWith(".fbx")).findAny() .orElseThrow(new BusinessException("找不到fbx文件")); return new FileObject(fbxFile.getName(), fbxUrl, null, "fbx"); } }