package cn.wisenergy.chnmuseum.party.web.controller; import cn.hutool.core.util.ArrayUtil; import cn.wisenergy.chnmuseum.party.common.dfs.FastDFSUtils; import cn.wisenergy.chnmuseum.party.common.enums.*; import cn.wisenergy.chnmuseum.party.common.mvc.InterfaceException; import cn.wisenergy.chnmuseum.party.common.util.TimeUtils; import cn.wisenergy.chnmuseum.party.common.vo.BatchUploadResVO; import cn.wisenergy.chnmuseum.party.common.vo.ImageUploadResult; import cn.wisenergy.chnmuseum.party.model.Asset; import cn.wisenergy.chnmuseum.party.service.AssetService; import cn.wisenergy.chnmuseum.party.web.controller.base.BaseController; import com.github.tobato.fastdfs.domain.fdfs.FileInfo; import com.github.tobato.fastdfs.domain.fdfs.MetaData; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.authz.annotation.RequiresPermissions; 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 javax.annotation.Resource; import java.io.IOException; import java.time.LocalDateTime; import java.util.*; /** * <p> * 文件上传 前端控制器 * </p> * * @author Danny Lee * @since 2021-03-16 */ @Slf4j @RestController @RequestMapping("/file") @Api(tags = {"文件上传接口"}) public class FileUploadController extends BaseController { private static final String[] IMAGE_TYPE = new String[]{"JPG", "JPEG", "PNG", "BMP", "WBMP"}; private static final String[] AUDIO_TYPE = new String[]{"MP3", "AAC", "WMA", "FLAC", "RM", "OGG"}; private static final String[] VIDEO_TYPE = new String[]{"MP4", "FLV"}; private static final String[] DOC_TYPE = new String[]{"PDF", "TXT", "DOC", "DOCX", "PPT", "PPTX", "XLS", "XLSX"}; private static final String[] DATUM_TYPE = ArrayUtil.addAll(DOC_TYPE, IMAGE_TYPE, AUDIO_TYPE, VIDEO_TYPE); @Resource private AssetService assetService; @ApiOperation(value = "根据文件ID刪除文件", notes = "根据文件ID刪除文件") @DeleteMapping(value = "/delete/{id}") @RequiresPermissions("file:delete") public ResponseEntity<Map<String, Object>> delete(@PathVariable(value = "id") String id) { final Asset asset = assetService.getById(id); if (asset != null) { final String fileUrl = asset.getFileUrl(); FastDFSUtils.deleteFile(fileUrl); this.assetService.removeById(id); } return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); } @ApiImplicitParams({ @ApiImplicitParam(name = "file", value = "资料", paramType = "form", dataType = "__file", collectionFormat = "array", allowMultiple = true) }) @PostMapping(value = "/datum/upload", headers = "content-type=multipart/form-data", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @ApiOperation(value = "展板资料上传", notes = "展板资料上传") public Map<String, Object> uploadFile(@RequestPart(value = "file", required = false) MultipartFile[] files) throws IOException { if (files.length == 0) { throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "没有文件可供上传"); } int successCount = 0; int failureCount = 0; List<BatchUploadResVO.HandleResult> handleList = new ArrayList<>(); List<Asset> datumUrlList = new ArrayList<>(); for (MultipartFile file : files) { // 当前维度表下线结果 BatchUploadResVO.HandleResult handleResult = new BatchUploadResVO.HandleResult(); // 原始文件名 String originalFilename = file.getOriginalFilename(); if (StringUtils.isBlank(originalFilename)) { handleResult.setFileName(""); handleResult.setFileUrl(""); handleResult.setHandleResult(HANDLE_STATUS_ENUM.FAILURE.getName()); handleResult.setDescription("文件名为空"); failureCount++; continue; } String extName = FilenameUtils.getExtension(originalFilename); boolean anyMatch = Arrays.stream(DATUM_TYPE).anyMatch(s -> Objects.equals(s, extName.toUpperCase())); if (anyMatch) { final Asset asset = Asset.builder() .fileName(originalFilename) .fileExtName(extName) .fileCat(FileCatEnum.EXHIBITION_BOARD_DATUM.name()) .build(); String fileUrl = null; final Set<MetaData> metaDataSet = new HashSet<>(); metaDataSet.add(new MetaData("fileName", originalFilename)); if (Arrays.stream(VIDEO_TYPE).anyMatch(s -> Objects.equals(s, extName.toUpperCase()))) { metaDataSet.add(new MetaData("fileType", FileTypeEnum.VIDEO.name())); handleResult.setFileType(FileTypeEnum.VIDEO.name()); asset.setFileType(FileTypeEnum.VIDEO.name()); fileUrl = FastDFSUtils.uploadVideo(file.getInputStream(), file.getSize(), originalFilename, metaDataSet); final Set<MetaData> fileMetaData = FastDFSUtils.getFileMetaData(fileUrl); String md5 = fileMetaData.stream().filter(x -> "MD5".equals(x.getName())).map(MetaData::getValue).findFirst().get(); asset.setMd5(md5); } else if (Arrays.stream(AUDIO_TYPE).anyMatch(s -> Objects.equals(s, extName.toUpperCase()))) { metaDataSet.add(new MetaData("fileType", FileTypeEnum.AUDIO.name())); handleResult.setFileType(FileTypeEnum.AUDIO.name()); asset.setFileType(FileTypeEnum.AUDIO.name()); fileUrl = FastDFSUtils.uploadFile(file.getInputStream(), file.getSize(), originalFilename, metaDataSet); } else if (Arrays.stream(IMAGE_TYPE).anyMatch(s -> Objects.equals(s, extName.toUpperCase()))) { metaDataSet.add(new MetaData("fileType", FileTypeEnum.IMAGE.name())); handleResult.setFileType(FileTypeEnum.IMAGE.name()); asset.setFileType(FileTypeEnum.IMAGE.name()); fileUrl = FastDFSUtils.uploadFile(file.getInputStream(), file.getSize(), originalFilename, metaDataSet); asset.setThumbnail(fileUrl); } else if (Arrays.stream(DOC_TYPE).anyMatch(s -> Objects.equals(s, extName.toUpperCase()))) { metaDataSet.add(new MetaData("fileType", FileTypeEnum.DOCUMENT.name())); handleResult.setFileType(FileTypeEnum.DOCUMENT.name()); asset.setFileType(FileTypeEnum.DOCUMENT.name()); fileUrl = FastDFSUtils.uploadFile(file.getInputStream(), file.getSize(), originalFilename, metaDataSet); } final FileInfo fileInfo = FastDFSUtils.getFileInfo(fileUrl); final LocalDateTime createTime = TimeUtils.getDateTimeOfTimestamp(fileInfo.getCreateTime()); asset.setFileSize(fileInfo.getFileSize()); asset.setFileUrl(fileUrl); asset.setFileCat(FileCatEnum.EXHIBITION_BOARD_DATUM.name()); asset.setCreateTime(createTime); asset.setUpdateTime(createTime); this.assetService.save(asset); datumUrlList.add(asset); handleResult.setFileUrl(fileUrl); handleResult.setFileName(originalFilename); handleResult.setHandleResult(HANDLE_STATUS_ENUM.SUCCESS.getName()); handleResult.setDescription(""); successCount++; } else { handleResult.setFileUrl(""); handleResult.setDescription("文件" + originalFilename + "格式不支持"); failureCount++; } // 设置处理的业务表信息 handleList.add(handleResult); } BatchUploadResVO batchUploadResVO = new BatchUploadResVO(); batchUploadResVO.setFailureCount(failureCount); batchUploadResVO.setSuccessCount(successCount); batchUploadResVO.setTotal(files.length); batchUploadResVO.setHandleList(handleList); batchUploadResVO.setFileList(datumUrlList); return getResult(batchUploadResVO); } @PostMapping(value = "/image/upload", headers = "content-type=multipart/form-data", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @RequiresPermissions("file:image:upload") @ApiOperation(value = "单图片上传(封面/缩略图)", notes = "单图片上传(封面/缩略图)") public Map<String, Object> uploadImage(@RequestParam(value = "file") MultipartFile uploadFile) throws Exception { if (uploadFile == null || uploadFile.getSize() == 0) { throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "没有文件可供上传"); } String fileName = uploadFile.getOriginalFilename(); String extension = FilenameUtils.getExtension(fileName); if (StringUtils.isBlank(extension)) { throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "文件格式不支持"); } boolean anyMatch = Arrays.stream(IMAGE_TYPE).anyMatch(s -> Objects.equals(s, extension.toUpperCase())); if (!anyMatch) { throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "文件格式不支持"); } final Set<MetaData> metaDataSet = new HashSet<>(); metaDataSet.add(new MetaData("fileName", fileName)); metaDataSet.add(new MetaData("fileType", FileTypeEnum.IMAGE.name())); String url = FastDFSUtils.uploadFile(uploadFile.getInputStream(), uploadFile.getSize(), fileName, metaDataSet); ImageUploadResult imageUploadResult = new ImageUploadResult(); imageUploadResult.setFileName(fileName); imageUploadResult.setFileExtName(extension); imageUploadResult.setFileSize(uploadFile.getSize()); imageUploadResult.setUrl(url); return getResult(imageUploadResult); } @PostMapping(value = "/upload/allType", headers = "content-type=multipart/form-data", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @RequiresPermissions("file:upload:allType") @ApiOperation(value = "单文件上传(不限格式)", notes = "单文件上传(不限格式)") public Map<String, Object> uploadAllType(@RequestParam(value = "file") MultipartFile uploadFile) throws Exception { if (uploadFile == null || uploadFile.getSize() == 0) { throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "没有文件可供上传"); } String fileName = uploadFile.getOriginalFilename(); String extension = FilenameUtils.getExtension(fileName); if (StringUtils.isBlank(extension)) { throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "文件格式不支持"); } final Set<MetaData> metaDataSet = new HashSet<>(); metaDataSet.add(new MetaData("fileName", fileName)); String url = FastDFSUtils.uploadFile(uploadFile.getInputStream(), uploadFile.getSize(), fileName, metaDataSet); ImageUploadResult imageUploadResult = new ImageUploadResult(); imageUploadResult.setFileName(fileName); imageUploadResult.setFileExtName(extension); imageUploadResult.setFileSize(uploadFile.getSize()); imageUploadResult.setUrl(url); return getResult(imageUploadResult); } @ApiImplicitParams({ @ApiImplicitParam(name = "file", value = "音频文件", paramType = "form", dataType = "__file", collectionFormat = "array", allowMultiple = true) }) @PostMapping(value = "/audio/upload", headers = "content-type=multipart/form-data", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @RequiresPermissions("audio:upload") @ApiOperation(value = "多音频上传", notes = "多音频上传") public Map<String, Object> uploadAudio(@RequestPart(value = "file", required = false) MultipartFile[] files) throws IOException { if (files == null || files.length == 0) { throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "没有文件可供上传"); } final boolean existChineseAudio = Arrays.stream(files).anyMatch(s -> Objects.requireNonNull(s.getOriginalFilename()).contains("汉语")); if (!existChineseAudio) { throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "必须包含汉语音频"); } int successCount = 0; int failureCount = 0; List<BatchUploadResVO.HandleResult> handleList = new ArrayList<>(); List<Asset> videoUrlList = new ArrayList<>(); for (MultipartFile file : files) { // 当前维度表下线结果 BatchUploadResVO.HandleResult handleResult = new BatchUploadResVO.HandleResult(); // 原始文件名 String originalFilename = file.getOriginalFilename(); if (StringUtils.isBlank(originalFilename)) { handleResult.setFileName(""); handleResult.setFileType(FileTypeEnum.AUDIO.getName()); handleResult.setFileUrl(""); handleResult.setHandleResult(HANDLE_STATUS_ENUM.FAILURE.getName()); handleResult.setDescription("文件名为空"); failureCount++; continue; } String extName = FilenameUtils.getExtension(originalFilename); boolean anyMatch = Arrays.stream(AUDIO_TYPE).anyMatch(s -> Objects.equals(s, extName.toUpperCase())); if (anyMatch) { String language = null; final Set<MetaData> metaDataSet = new HashSet<>(); metaDataSet.add(new MetaData("fileName", originalFilename)); metaDataSet.add(new MetaData("fileType", FileTypeEnum.AUDIO.name())); if (originalFilename.contains("汉语")) { metaDataSet.add(new MetaData("language", LanguageEnum.ZH.name())); language = LanguageEnum.ZH.name(); } else if (originalFilename.contains("英语")) { metaDataSet.add(new MetaData("language", LanguageEnum.EN.name())); language = LanguageEnum.EN.name(); } else if (originalFilename.contains("蒙语")) { metaDataSet.add(new MetaData("language", LanguageEnum.MN.name())); language = LanguageEnum.MN.name(); } else if (originalFilename.contains("藏语")) { metaDataSet.add(new MetaData("language", LanguageEnum.BO.name())); language = LanguageEnum.BO.name(); } else if (originalFilename.contains("维吾尔语")) { metaDataSet.add(new MetaData("language", LanguageEnum.UYG.name())); language = LanguageEnum.UYG.name(); } String fileUrl = FastDFSUtils.uploadFile(file.getInputStream(), file.getSize(), originalFilename, metaDataSet); final FileInfo fileInfo = FastDFSUtils.getFileInfo(fileUrl); final LocalDateTime createTime = TimeUtils.getDateTimeOfTimestamp(fileInfo.getCreateTime()); final long fileSize = fileInfo.getFileSize(); final Asset asset = Asset.builder() .fileName(originalFilename) .fileExtName(extName) .fileType(FileTypeEnum.AUDIO.name()) .fileUrl(fileUrl) .fileSize(fileSize) .fileCat(FileCatEnum.EXHIBITION_BOARD_AUDIO.name()) .language(language) .createTime(createTime) .updateTime(createTime) .build(); this.assetService.save(asset); videoUrlList.add(asset); handleResult.setFileUrl(fileUrl); handleResult.setFileName(originalFilename); handleResult.setFileType(FileTypeEnum.AUDIO.getName()); handleResult.setHandleResult(HANDLE_STATUS_ENUM.SUCCESS.getName()); handleResult.setDescription(""); successCount++; } else { handleResult.setFileUrl(""); handleResult.setFileType(FileTypeEnum.AUDIO.getName()); handleResult.setHandleResult(HANDLE_STATUS_ENUM.FAILURE.getName()); handleResult.setDescription("文件" + originalFilename + "格式不支持"); failureCount++; } // 设置处理的业务表信息 handleList.add(handleResult); } BatchUploadResVO batchUploadResVO = new BatchUploadResVO(); batchUploadResVO.setFailureCount(failureCount); batchUploadResVO.setSuccessCount(successCount); batchUploadResVO.setTotal(files.length); batchUploadResVO.setHandleList(handleList); batchUploadResVO.setFileList(videoUrlList); return getResult(batchUploadResVO); } @ApiImplicitParams({ @ApiImplicitParam(name = "file", value = "视频文件", paramType = "form", dataType = "__file", collectionFormat = "array", allowMultiple = true) }) @PostMapping(value = "/video/upload", headers = "content-type=multipart/form-data", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @RequiresPermissions("video:upload") @ApiOperation(value = "视频上传", notes = "视频上传") public Map<String, Object> uploadVideo(@RequestPart(value = "file", required = true) MultipartFile[] files) throws IOException { if (files == null || files.length == 0) { throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "没有文件可供上传"); } final boolean matchChinese = Arrays.stream(files).anyMatch(s -> Objects.requireNonNull(s.getOriginalFilename()).contains("汉语")); if (!matchChinese) { throw new InterfaceException(RESPONSE_CODE_ENUM.SERVER_ERROR.getResultCode(), "文件必须包含汉语视频"); } int successCount = 0; int failureCount = 0; List<BatchUploadResVO.HandleResult> handleList = new ArrayList<>(); List<Asset> fileList = new ArrayList<>(); for (MultipartFile file : files) { // 当前维度表下线结果 BatchUploadResVO.HandleResult handleResult = new BatchUploadResVO.HandleResult(); // 原始文件名 String originalFilename = file.getOriginalFilename(); if (StringUtils.isBlank(originalFilename)) { handleResult.setFileName(""); handleResult.setFileType(FileTypeEnum.VIDEO.getName()); handleResult.setFileUrl(""); handleResult.setHandleResult(HANDLE_STATUS_ENUM.FAILURE.getName()); handleResult.setDescription("文件名为空"); failureCount++; continue; } String extName = FilenameUtils.getExtension(originalFilename); boolean anyMatch = Arrays.stream(VIDEO_TYPE).anyMatch(s -> Objects.equals(s, extName.toUpperCase())); if (anyMatch) { String language = null; final Set<MetaData> metaDataSet = new HashSet<>(); metaDataSet.add(new MetaData("fileName", originalFilename)); metaDataSet.add(new MetaData("fileType", FileTypeEnum.VIDEO.name())); if (originalFilename.contains("汉语")) { metaDataSet.add(new MetaData("language", LanguageEnum.ZH.name())); language = LanguageEnum.ZH.name(); } else if (originalFilename.contains("英语")) { metaDataSet.add(new MetaData("language", LanguageEnum.EN.name())); language = LanguageEnum.EN.name(); } else if (originalFilename.contains("蒙语")) { metaDataSet.add(new MetaData("language", LanguageEnum.MN.name())); language = LanguageEnum.MN.name(); } else if (originalFilename.contains("藏语")) { metaDataSet.add(new MetaData("language", LanguageEnum.BO.name())); language = LanguageEnum.BO.name(); } else if (originalFilename.contains("维吾尔语")) { metaDataSet.add(new MetaData("language", LanguageEnum.UYG.name())); language = LanguageEnum.UYG.name(); } String fileUrl = FastDFSUtils.uploadVideo(file.getInputStream(), file.getSize(), originalFilename, metaDataSet); final FileInfo fileInfo = FastDFSUtils.getFileInfo(fileUrl); final Set<MetaData> fileMetaData = FastDFSUtils.getFileMetaData(fileUrl); String md5 = fileMetaData.stream().filter(x -> "MD5".equals(x.getName())).map(MetaData::getValue).findFirst().get(); final LocalDateTime createTime = TimeUtils.getDateTimeOfTimestamp(fileInfo.getCreateTime()); final long fileSize = fileInfo.getFileSize(); final Asset asset = Asset.builder() .fileName(originalFilename) .fileExtName(extName) .fileType(FileTypeEnum.VIDEO.name()) .fileSize(fileSize) .fileUrl(fileUrl) .fileCat(FileCatEnum.VIDEO_CONTENT.name()) .language(language) .md5(md5) .createTime(createTime) .updateTime(createTime) .build(); this.assetService.save(asset); fileList.add(asset); handleResult.setFileUrl(fileUrl); handleResult.setFileName(originalFilename); handleResult.setFileType(FileTypeEnum.VIDEO.getName()); handleResult.setHandleResult(HANDLE_STATUS_ENUM.SUCCESS.getName()); handleResult.setHandleResult(HANDLE_STATUS_ENUM.SUCCESS.getName()); handleResult.setDescription(""); successCount++; } else { handleResult.setFileUrl(""); handleResult.setHandleResult("上传失败"); handleResult.setDescription("文件" + originalFilename + "格式不支持"); failureCount++; } // 设置处理的业务表信息 handleList.add(handleResult); } BatchUploadResVO batchUploadResVO = new BatchUploadResVO(); batchUploadResVO.setFailureCount(failureCount); batchUploadResVO.setSuccessCount(successCount); batchUploadResVO.setTotal(files.length); batchUploadResVO.setHandleList(handleList); batchUploadResVO.setFileList(fileList); return getResult(batchUploadResVO); } }