New file |
| | |
| | | package com.moral.api.service.impl; |
| | | |
| | | import com.moral.api.config.Interceptor.UserHelper; |
| | | import com.moral.api.entity.FileTable; |
| | | import com.moral.api.exception.BusinessException; |
| | | import com.moral.api.mapper.FileTableMapper; |
| | | import com.moral.api.pojo.enums.FileType; |
| | | import com.moral.api.pojo.enums.YesOrNo; |
| | | import com.moral.api.pojo.vo.file.FileVo; |
| | | import com.moral.api.pojo.vo.user.QxUser; |
| | | import com.moral.api.service.FileTableService; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.moral.api.utils.FileTypeUtils; |
| | | import com.moral.api.utils.StringUtils; |
| | | import com.moral.util.DateUtils; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import net.coobird.thumbnailator.Thumbnails; |
| | | import org.apache.commons.collections4.CollectionUtils; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.*; |
| | | import java.net.URLEncoder; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * <p> |
| | | * 附件表 服务实现类 |
| | | * </p> |
| | | * |
| | | * @author moral |
| | | * @since 2023-09-21 |
| | | */ |
| | | @Service |
| | | @Slf4j |
| | | public class FileTableServiceImpl extends ServiceImpl<FileTableMapper, FileTable> implements FileTableService { |
| | | @Value("${file.path}") |
| | | private String basePath; |
| | | @Override |
| | | public FileVo upload(MultipartFile file, Integer sysCode) { |
| | | String originalFilename = file.getOriginalFilename().replaceAll(StringUtils.SPACE, StringUtils.EMPTY).toLowerCase(); |
| | | String suffix = originalFilename.substring(originalFilename.lastIndexOf(StringUtils.DOT)); |
| | | FileType fileType = FileTypeUtils.getFileType(suffix.toLowerCase()); |
| | | // 处理文件相对路径 系统代码 + 业务代码 + 日期 |
| | | String filePath = getFilePath(sysCode.toString()); |
| | | // 保存文件 |
| | | String targetFolder = basePath.replaceAll(StringUtils.BACKSLASH.concat(StringUtils.BACKSLASH), StringUtils.SLASH).concat(StringUtils.SLASH).concat(filePath); |
| | | //使用uuid 替换上传文件名,避免重复 |
| | | String storageFileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf(StringUtils.DOT)); |
| | | storageFile(file, storageFileName, targetFolder); |
| | | |
| | | // 封装文件信息 |
| | | QxUser user = UserHelper.getCurrentUser(); |
| | | FileTable sysFile = new FileTable(); |
| | | sysFile.setFileName(originalFilename).setFileType(fileType.getValue()).setFileSize((int) file.getSize()).setFileAddress(filePath.concat(storageFileName)) |
| | | .setFileModule(sysCode).setCreateTime(new Date()); |
| | | if (Objects.nonNull(user)) { |
| | | sysFile.setCreateId(user.getUserId()).setCreateName(user.getUserName()); |
| | | } |
| | | save(sysFile); |
| | | return new FileVo().setFileId(sysFile.getFileId()).setFileName(originalFilename).setFileType(fileType.getValue()); |
| | | } |
| | | |
| | | @Override |
| | | public List<FileVo> upload(List<MultipartFile> files, Integer sysCode) { |
| | | List<FileVo> fileList = new LinkedList<>(); |
| | | for (MultipartFile file : files) { |
| | | fileList.add(upload(file, sysCode)); |
| | | } |
| | | return fileList; |
| | | } |
| | | |
| | | @Override |
| | | public void preview(Integer id, HttpServletRequest request, HttpServletResponse response) { |
| | | FileTable sysFile = getById(id); |
| | | File file = new File(handleFileRealPath(sysFile.getFileAddress())); |
| | | String suffix = file.getName().substring(file.getName().lastIndexOf(StringUtils.DOT)); |
| | | if (FileTypeUtils.SUFFIX_MP4.equals(suffix)) { |
| | | videoPreview(file, request, response); |
| | | } else { |
| | | try (OutputStream out = response.getOutputStream(); InputStream in = new FileInputStream(file)) { |
| | | response.setContentType(FileTypeUtils.convertHeaderType(suffix)); |
| | | response.setHeader("Content-Disposition", "inline; filename=" + URLEncoder.encode(sysFile.getFileName(), "UTF-8")); |
| | | int len; |
| | | // 创建数据缓冲区 |
| | | byte[] buffer = new byte[1024]; |
| | | while ((len = in.read(buffer)) > 0) { |
| | | out.write(buffer, 0, len); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("读取文件异常!!! e={}", e.getMessage()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private String getFilePath(String sysCode) { |
| | | return sysCode.concat(StringUtils.SLASH).concat(StringUtils.SLASH).concat(DateUtils.dateToDateString(new Date(),DateUtils.yyyyMMdd_EN)).concat(StringUtils.SLASH); |
| | | } |
| | | |
| | | public void storageFile(MultipartFile file, String originalFilename, String targetFolder) { |
| | | File f = new File(targetFolder, originalFilename); |
| | | try { |
| | | // 保存文件 |
| | | if (!f.getParentFile().exists()) { |
| | | if (!f.getParentFile().mkdirs()) { |
| | | log.error("error:创建文件失败! dir={}", f.getAbsolutePath()); |
| | | } |
| | | } |
| | | file.transferTo(f); |
| | | } catch (IOException e) { |
| | | log.error("error:文件上传失败!!!e={}", e.getMessage()); |
| | | throw new BusinessException("文件上传失败,请重试!"); |
| | | } |
| | | } |
| | | private String handleFileRealPath(String path) { |
| | | return basePath.replaceAll(StringUtils.BACKSLASH.concat(StringUtils.BACKSLASH), StringUtils.SLASH).concat(StringUtils.SLASH).concat(path); |
| | | } |
| | | private void videoPreview(File file, HttpServletRequest request, HttpServletResponse response) { |
| | | String suffix = file.getName().substring(file.getName().lastIndexOf(StringUtils.DOT)); |
| | | //设置属性 |
| | | response.setContentType(FileTypeUtils.convertHeaderType(suffix)); |
| | | response.setHeader("Accept-Ranges", "bytes"); |
| | | response.setHeader("ETag", file.getName()); |
| | | response.setHeader("Last-Modified", new Date().toString()); |
| | | long contentLength = file.length(); |
| | | |
| | | //每次传递实际长度(初始第一次读取少选数据) |
| | | long length = Math.min(contentLength, 1024); |
| | | long start = 0, end = 0; |
| | | String range = request.getHeader("Range"); |
| | | //第一次请求只返回content length来让客户端请求多次实际数据 |
| | | if (range == null) { |
| | | response.setHeader("Content-length", contentLength + ""); |
| | | } else { |
| | | //以后的多次以断点续传的方式来返回视频数据 |
| | | response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);//206 |
| | | |
| | | if (range.startsWith("bytes=")) { |
| | | String[] values = range.split("=")[1].split("-"); |
| | | start = Integer.parseInt(values[0]); |
| | | if (values.length > 1) { |
| | | end = Integer.parseInt(values[1]); |
| | | } |
| | | } |
| | | //无end,每次允许的最大长度 |
| | | long maxSize = 1024 * 1024; //1MB |
| | | if (end > 0) { |
| | | length = end - start + 1; |
| | | response.setHeader("Content-length", "" + length); |
| | | response.setHeader("Content-Range", "bytes " + start + "-" + end + "/" + contentLength); |
| | | } else { |
| | | length = Math.min((contentLength - start), maxSize); |
| | | response.setHeader("Content-length", "" + length); |
| | | response.setHeader("Content-Range", "bytes " + start + "-" + (start + length - 1) + "/" + contentLength); |
| | | } |
| | | } |
| | | try { |
| | | FileInputStream fileInputStream = new FileInputStream(file); |
| | | OutputStream out = response.getOutputStream(); |
| | | //将数据截取并存入byte[]数组中 |
| | | byte[] data = new byte[(int) length]; |
| | | fileInputStream.skip(start); |
| | | fileInputStream.read(data); |
| | | //取出要传给前端的有效数据 |
| | | out.write(data); |
| | | out.close(); |
| | | fileInputStream.close(); |
| | | } catch (Exception e) { |
| | | log.error("读取文件异常!!! e={}", e.getMessage()); |
| | | } |
| | | } |
| | | @Override |
| | | public void coverPreview(Integer id, HttpServletRequest request, HttpServletResponse response) { |
| | | FileTable sysFile = getById(id); |
| | | |
| | | File file = new File(handleFileRealPath(sysFile.getFileAddress())); |
| | | String suffix = file.getName().substring(file.getName().lastIndexOf(StringUtils.DOT)); |
| | | |
| | | try (OutputStream out = response.getOutputStream()) { |
| | | response.setContentType(FileTypeUtils.convertHeaderType(suffix)); |
| | | response.setHeader("Content-Disposition", "inline; filename=" + URLEncoder.encode(sysFile.getFileName(), "UTF-8")); |
| | | Thumbnails.of(file).size(420, 200).toOutputStream(out); |
| | | } catch (Exception e) { |
| | | log.error("读取文件异常!!! e={}", e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional |
| | | public void upDateResult(List<FileVo> list,int relationId,int fileModule) { |
| | | List<FileTable> existsList = this.lambdaQuery().eq(FileTable::getRelationId, relationId) |
| | | .eq(FileTable::getFileModule, fileModule) |
| | | .eq(FileTable::getIsDel, YesOrNo.NO.value).list(); |
| | | |
| | | // 新增附件 |
| | | if (!CollectionUtils.isEmpty(list)) { |
| | | List<FileTable> addList = new ArrayList(); |
| | | // 2.2.筛选出需要保存的文件 |
| | | list.forEach(it -> { |
| | | existsList.removeIf(file -> file.getFileId().equals(it.getFileId())); |
| | | FileTable file = new FileTable(); |
| | | BeanUtils.copyProperties(it,file); |
| | | file.setRelationId(relationId); |
| | | addList.add(file); |
| | | }); |
| | | if (!CollectionUtils.isEmpty(addList)) { |
| | | // 保存 |
| | | this.updateBatchById(addList); |
| | | } |
| | | } |
| | | // 删除附件 |
| | | if (!CollectionUtils.isEmpty(existsList)) { |
| | | removeByIds(existsList.stream().map(FileTable::getFileId).collect(Collectors.toList())); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public List<FileVo> list(int relationId, int fileModule) { |
| | | List<FileVo> list = new ArrayList<>(); |
| | | List<FileTable> existsList = this.lambdaQuery().eq(FileTable::getRelationId, relationId) |
| | | .eq(FileTable::getFileModule, fileModule) |
| | | .eq(FileTable::getIsDel, YesOrNo.NO.value).orderByAsc(FileTable::getCreateTime).list(); |
| | | existsList.forEach(it->{ |
| | | FileVo fileVo = new FileVo(); |
| | | fileVo.setFileId(it.getFileId()); |
| | | fileVo.setFileName(it.getFileName()); |
| | | fileVo.setFileType(it.getFileType()); |
| | | list.add(fileVo); |
| | | }); |
| | | return list; |
| | | } |
| | | } |