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.bytedeco.javacv.FFmpegFrameGrabber; import org.bytedeco.javacv.Frame; import org.bytedeco.javacv.Java2DFrameConverter; import org.pngquant.PngQuant; 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.Base64; import java.util.Date; import java.util.Objects; import java.util.Optional; 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) { 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); } else if ("png".equals(ext)) { img = ImageUtils.resizePng(file.getInputStream(), width, height, true); } ByteArrayOutputStream os = new ByteArrayOutputStream(); ImageIO.write(img, ext, os); InputStream is = new ByteArrayInputStream(os.toByteArray()); return storageService.uploadFromInputStream(is, path); } else if (width != null || height != null) { 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); } else if ("png".equals(ext)) { img = ImageUtils.resizePng(file.getInputStream(), width, height, false); } 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) { 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(new FileInputStream(tmpFile), width, height); } else { img = ImageUtils.resizePng(new FileInputStream(tmpFile), width, height, true); } ByteArrayOutputStream os = new ByteArrayOutputStream(); ImageIO.write(img, ext, os); InputStream is = new ByteArrayInputStream(os.toByteArray()); url = storageService.uploadFromInputStream(is, path); } else if (Pattern.matches("(jpg|png)", ext) && (width != null || height != null)) { 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(new FileInputStream(tmpFile), width, height); } else { img = ImageUtils.resizePng(new FileInputStream(tmpFile), width, height, false); } 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)) { FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(tmpFile); frameGrabber.start(); Java2DFrameConverter aa = new Java2DFrameConverter(); try { BufferedImage bi; Frame f = frameGrabber.grabKeyFrame(); bi = aa.convert(f); File thumbFile = null; while (bi != null) { thumbFile = File.createTempFile("video_thumb_", ".png"); PngQuant pngQuant = new PngQuant(); ImageIO.write(pngQuant.getRemapped(bi), "png", thumbFile); f = frameGrabber.grabKeyFrame(); bi = aa.convert(f); } Objects.requireNonNull(thumbFile); String thumbPath = "thumb_image/" + new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + RandomStringUtils.randomAlphabetic(8) + ".png"; thumbUrl = storageService.uploadFromInputStream(new FileInputStream(thumbFile), thumbPath); } catch (Exception e) { e.printStackTrace(); } finally { frameGrabber.stop(); } } return new FileObject(file.getOriginalFilename(), url, thumbUrl, file.getContentType()); } }