package com.artfess.file.controller; import cn.hutool.core.io.IoUtil; import com.artfess.base.annotation.ApiGroup; import com.artfess.base.attachment.AttachmentService; import com.artfess.base.attachment.AttachmentServiceFactory; import com.artfess.base.constants.ApiGroupConsts; import com.artfess.base.enums.FileTypeEnum; import com.artfess.base.exception.NotFoundException; import com.artfess.base.handler.MultiTenantHandler; import com.artfess.base.handler.MultiTenantIgnoreResult; import com.artfess.base.model.CommonResult; import com.artfess.base.util.AppUtil; import com.artfess.base.util.BeanUtils; import com.artfess.base.util.FileUtil; import com.artfess.base.util.JsonUtil; import com.artfess.base.util.StringUtil; import com.artfess.file.attachmentService.FtpAttachmentServiceImpl; import com.artfess.file.model.DefaultFile; import com.artfess.file.persistence.manager.FileManager; import com.artfess.file.service.FilePreview; import com.artfess.file.service.FilePreviewFactory; import com.artfess.file.util.AppFileUtil; import com.artfess.file.util.FileUtils; import com.artfess.file.util.MinioUtil; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import lombok.extern.slf4j.Slf4j; import org.apache.catalina.connector.ClientAbortException; import org.springframework.beans.factory.annotation.Value; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.activation.MimetypesFileTypeMap; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; /** * 附件在线预览 * * @company 阿特菲斯信息技术有限公司 * @author:lj * @date:2018年6月14日 */ @Slf4j @RestController @RequestMapping("/file/onlinePreviewController/v1") @Api(tags = "附件在线预览") @ApiGroup(group = {ApiGroupConsts.GROUP_SYSTEM}) @SuppressWarnings({"rawtypes"}) public class OnlinePreviewController { @Resource FilePreviewFactory previewFactory; @Resource FileManager fileManager; @Resource FileUtils fileUtils; @Value("${file.file.dir}") String fileDir; @RequestMapping(value = "onlinePreview", method = RequestMethod.GET, produces = {"application/json; charset=utf-8"}) @ApiOperation(value = "附件在线预览", httpMethod = "GET", notes = "附件在线预览") public JsonNode onlinePreview(HttpServletRequest request, HttpServletResponse response, @ApiParam(name = "fileId", value = "附件ID") @RequestParam String fileId) throws Exception { Map map = new HashMap(); DefaultFile fileMode = fileManager.get(fileId); if (fileMode != null) { AttachmentServiceFactory attachmentHandlerFactory = AppUtil.getBean(AttachmentServiceFactory.class); String saveType = null; if (!StringUtil.isEmpty(fileMode.getStoreType())) { fileMode.setProp6(fileMode.getStoreType()); saveType = fileMode.getStoreType(); } if (StringUtil.isEmpty(saveType)) { saveType = AppFileUtil.getSaveType(fileMode.getProp6()); if (StringUtil.isEmpty(saveType)) { saveType = AppFileUtil.getFileSaveTypeByConfig(BeanUtils.isNotEmpty(fileMode) ? fileMode.getBizCode() : ""); } } AttachmentService attachmentService = attachmentHandlerFactory.getCurrentServices(saveType); //特殊场景,附件上传方式是ftpsaveType,word套打生成的文件是磁盘存储,下载套打文件时特殊处理 if (attachmentService instanceof FtpAttachmentServiceImpl && DefaultFile.SAVE_TYPE_FOLDER.equals(fileMode.getStoreType())) { attachmentService = attachmentHandlerFactory.getCurrentServices(DefaultFile.SAVE_TYPE_FOLDER); } FilePreview filePreview = previewFactory.get(fileMode); String Result = filePreview.filePreviewHandle(fileMode, map); map.put("result", Result); map.remove("project"); } JsonNode object = JsonUtil.toJsonNode(map); return object; } @RequestMapping(value = "getFileByPathAndId_{fileId}_{ext}", method = RequestMethod.GET, produces = {"application/json; charset=utf-8"}) @ApiOperation(value = "根据ID和类型找到处理后的附件", httpMethod = "GET", notes = "根据ID和类型找到附件") public void getFileByPathAndId(HttpServletRequest request, HttpServletResponse response, @PathVariable(name = "fileId") String fileId, @PathVariable(name = "ext") String ext) throws IOException { String fullPath = fileDir + fileId + "." + ext; String type = "text/html;charset=" + getCharset(fullPath); if ("pdf".equals(ext)) { type = "application/pdf"; } response.setContentType(type); byte[] bytes = FileUtil.readByte(fullPath); if (bytes != null && bytes.length > 0) { response.getOutputStream().write(bytes); } } @RequestMapping(value = "getFileById_{fileId}", method = RequestMethod.GET, produces = {"application/json; charset=utf-8"}) @ApiOperation(value = "根据文件ID找到上传过的文件", httpMethod = "GET", notes = "根据文件ID找到上传过的文件") public void getFileById(HttpServletRequest request, HttpServletResponse response, @PathVariable(name = "fileId") String fileId) throws Exception { DefaultFile file = null; try (MultiTenantIgnoreResult setThreadLocalIgnore = MultiTenantHandler.setThreadLocalIgnore()) { file = fileManager.get(fileId); } if (BeanUtils.isEmpty(file)) { throw new NotFoundException(String.format("未找到fileId为: %s 的文件", fileId)); } String fileName = file.getFileName() + "." + file.getExtensionName(); String filedisplay = URLEncoder.encode(fileName, "utf-8"); response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); response.addHeader("Content-Disposition", "attachment;filename=" + filedisplay); response.addHeader("filename", filedisplay); response.setHeader("Access-Control-Allow-Origin", "*"); String type = new MimetypesFileTypeMap().getContentType(new File(file.getFilePath())); response.setContentType(type); fileManager.downloadFile(fileId, response.getOutputStream()); } //根据文件路径获取文件编码格式 public static String getCharset(String pathName) { File file = new File(pathName); if (!file.exists()) { return ""; } String charset = "GBK"; byte[] first3Bytes = new byte[3]; BufferedInputStream bis = null; try { boolean checked = false; bis = new BufferedInputStream(new FileInputStream(file)); bis.mark(0); int read = bis.read(first3Bytes, 0, 3); if (read == -1) return charset; if (first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE) { charset = "UTF-16LE"; checked = true; } else if (first3Bytes[0] == (byte) 0xFE && first3Bytes[1] == (byte) 0xFF) { charset = "UTF-16BE"; checked = true; } else if (first3Bytes[0] == (byte) 0xEF && first3Bytes[1] == (byte) 0xBB && first3Bytes[2] == (byte) 0xBF) { charset = "UTF-8"; checked = true; } bis.reset(); if (!checked) { while ((read = bis.read()) != -1) { if (read >= 0xF0) break; if (0x80 <= read && read <= 0xBF) break; if (0xC0 <= read && read <= 0xDF) { read = bis.read(); if (0x80 <= read && read <= 0xBF) continue; else break; } else if (0xE0 <= read && read <= 0xEF) { read = bis.read(); if (0x80 <= read && read <= 0xBF) { read = bis.read(); if (0x80 <= read && read <= 0xBF) { charset = "UTF-8"; break; } else break; } else break; } } } bis.close(); } catch (Exception e) { e.printStackTrace(); } finally { try { bis.close(); } catch (IOException e) { } } return charset; } @RequestMapping(value = "minioUrl/{fileId}", method = RequestMethod.GET, produces = {"application/json; charset=utf-8"}) @ApiOperation(value = "根据文件ID获取minio上传的文件免签url", httpMethod = "GET", notes = "根据文件ID获取minio上传的文件免签url") public CommonResult minioUrl(@PathVariable(name = "fileId") String fileId) throws Exception { return CommonResult.success(fileManager.minioUrl(fileId), null); } }