package org.jeecg.modules.doc.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.apache.shiro.SecurityUtils; import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.util.DateUtils; import org.jeecg.modules.doc.component.*; import org.jeecg.modules.doc.constant.Constant; import org.jeecg.modules.doc.dto.DownloadFileDTO; import org.jeecg.modules.doc.dto.PreviewDTO; import org.jeecg.modules.doc.dto.UploadFileDTO; import org.jeecg.modules.doc.entity.*; import org.jeecg.modules.doc.enums.UploadFileStatusEnum; import org.jeecg.modules.doc.mapper.*; import org.jeecg.modules.doc.service.IFiletransferService; import org.jeecg.modules.doc.service.IUserStorageFlowService; import org.jeecg.modules.doc.util.UFOPUtils; import org.jeecg.modules.doc.vo.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.image.BufferedImage; import java.io.*; import java.net.URI; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.zip.Adler32; import java.util.zip.CheckedOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @Slf4j @Service @Transactional(rollbackFor=Exception.class) public class FiletransferService implements IFiletransferService { @Resource DocFileMapper docFileMapper; @Resource DocFilePathMapper docFilePathMapper; @Resource UploadTaskDetailMapper uploadTaskDetailMapper; @Resource UploadTaskMapper uploadTaskMapper; @Resource DocFileDealComp fileDealComp; @Resource ImageMapper imageMapper; @Autowired RestTemplate restTemplate; @Autowired IUserStorageFlowService userStorageFlowService; @Override public UploadFileVo uploadFileSpeed(UploadFileDTO uploadFileDTO) { LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); UploadFileVo uploadFileVo = new UploadFileVo(); Map param = new HashMap<>(); param.put("identifier", uploadFileDTO.getIdentifier()); // 查询是否已存在相同文件 List list = docFileMapper.selectList(new LambdaQueryWrapper().eq(DocFile::getIdentifier,uploadFileDTO.getIdentifier())); String filePath = uploadFileDTO.getFilePath(); String relativePath = uploadFileDTO.getRelativePath(); QiwenFile qiwenFile = null; if (relativePath.contains("/")) { qiwenFile = new QiwenFile(filePath, relativePath, false); } else { qiwenFile = new QiwenFile(filePath, uploadFileDTO.getFilename(), false); } // 有相同文件 if (list != null && !list.isEmpty()) { DocFile file = list.get(0); DocFilePath userFile = new DocFilePath(qiwenFile, file.getFileId()); DocFilePath parent = fileDealComp.getParent(userFile.getFilePath()); if (parent != null) { userFile.setParentId(parent.getPathId()); } // 查询用户文件是否已存在 DocFilePath param1 = PathFileUtil.searchParam(userFile); List FilePathList = docFilePathMapper.selectList(new QueryWrapper<>(param1)); if (FilePathList.size() <= 0) { docFilePathMapper.insert(userFile); //fileDealComp.uploadESByUserFileId(userFile.getUserFileId()); } if (relativePath.contains("/")) { fileDealComp.restoreParentFilePath(qiwenFile, userFile.getPathId()); } // 已极速上传,文件不用再上传 uploadFileVo.setSkipUpload(true); } else { // 需要上传 uploadFileVo.setSkipUpload(false); // 查询已上传块 List uploaded = uploadTaskDetailMapper.selectUploadedChunkNumList(uploadFileDTO.getIdentifier()); if (uploaded != null && !uploaded.isEmpty()) { uploadFileVo.setUploaded(uploaded); } else { // 添加上传任务 LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(UploadTask::getIdentifier, uploadFileDTO.getIdentifier()); List rslist = uploadTaskMapper.selectList(lambdaQueryWrapper); if (rslist == null || rslist.isEmpty()) { UploadTask uploadTask = new UploadTask(); uploadTask.setIdentifier(uploadFileDTO.getIdentifier()); uploadTask.setUploadTime(DateUtils.getDataString(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))); uploadTask.setUploadStatus(UploadFileStatusEnum.UNCOMPLATE.getCode()); uploadTask.setFileName(qiwenFile.getNameNotExtend()); uploadTask.setFilePath(qiwenFile.getParent()); uploadTask.setExtendName(qiwenFile.getExtendName()); uploadTask.setUserId(loginUser.getUserIdentity()); uploadTaskMapper.insert(uploadTask); } } } return uploadFileVo; } @Override public void uploadFile(HttpServletRequest request, UploadFileDTO uploadFileDto) { UploadFile uploadFile = new UploadFile(); uploadFile.setChunkNumber(uploadFileDto.getChunkNumber()); uploadFile.setChunkSize(uploadFileDto.getChunkSize()); uploadFile.setTotalChunks(uploadFileDto.getTotalChunks()); uploadFile.setIdentifier(uploadFileDto.getIdentifier()); uploadFile.setTotalSize(uploadFileDto.getTotalSize()); uploadFile.setCurrentChunkSize(uploadFileDto.getCurrentChunkSize()); Uploader uploader = new LocalStorageUploader(); if (uploader == null) { log.error("上传失败,请检查storageType是否配置正确"); throw new UploadException("上传失败"); } List uploadFileResultList; try { uploadFileResultList = uploader.upload(request, uploadFile); } catch (Exception e) { log.error("上传失败,请检查UFOP连接配置是否正确"); throw new UploadException("上传失败", e); } for (int i = 0; i < uploadFileResultList.size(); i++){ UploadFileResult uploadFileResult = uploadFileResultList.get(i); String relativePath = uploadFileDto.getRelativePath(); QiwenFile qiwenFile = null; if (relativePath.contains("/")) { qiwenFile = new QiwenFile(uploadFileDto.getFilePath(), relativePath, false); } else { qiwenFile = new QiwenFile(uploadFileDto.getFilePath(), uploadFileDto.getFilename(), false); } if (UploadFileStatusEnum.SUCCESS.equals(uploadFileResult.getStatus())){ // log.info("开始保存===文件路径:{},文件名:{},文件唯一标识:{}", uploadFileResult.getFileUrl(), uploadFileResult.getFileName(), uploadFileResult.getIdentifier()); DocFile fileBean = new DocFile(uploadFileResult); docFileMapper.insert(fileBean); DocFilePath userFile = new DocFilePath(qiwenFile, fileBean.getFileId()); DocFilePath param = PathFileUtil.searchParam(userFile); List userFileList = docFilePathMapper.selectList(new QueryWrapper<>(param)); if (userFileList.size() > 0) { String fileName = fileDealComp.getRepeatFileName(userFile, userFile.getFilePath()); userFile.setFileName(fileName); } DocFilePath parent = fileDealComp.getParent(userFile.getFilePath()); if (parent!=null) { userFile.setParentId(parent.getPathId()); } try { docFilePathMapper.insert(userFile); } catch (Exception e) { log.error("上传文件异常:" + e.getMessage()); } if (relativePath.contains("/")) { fileDealComp.restoreParentFilePath(qiwenFile, userFile.getPathId()); } // fileDealComp.uploadESByUserFileId(userFile.getUserFileId()); LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(UploadTaskDetail::getIdentifier, uploadFileDto.getIdentifier()); uploadTaskDetailMapper.delete(lambdaQueryWrapper); LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); lambdaUpdateWrapper.set(UploadTask::getUploadStatus, UploadFileStatusEnum.SUCCESS.getCode()) .eq(UploadTask::getIdentifier, uploadFileDto.getIdentifier()); uploadTaskMapper.update(null, lambdaUpdateWrapper); try { if (UFOPUtils.isImageFile(uploadFileResult.getExtendName())) { BufferedImage src = uploadFileResult.getBufferedImage(); Image image = new Image(); image.setImageWidth(src.getWidth()); image.setImageHeight(src.getHeight()); image.setFileId(fileBean.getFileId()); imageMapper.insert(image); } } catch (Exception e) { log.error("生成图片缩略图失败!", e); } // fileDealComp.parseMusicFile(uploadFileResult.getExtendName(), uploadFileResult.getStorageType().getCode(), uploadFileResult.getFileUrl(), fileBean.getFileId()); } else if (UploadFileStatusEnum.UNCOMPLATE.equals(uploadFileResult.getStatus())) { UploadTaskDetail uploadTaskDetail = new UploadTaskDetail(); uploadTaskDetail.setFilePath(qiwenFile.getParent()); uploadTaskDetail.setFileName(qiwenFile.getNameNotExtend()); uploadTaskDetail.setChunkNumber(uploadFileDto.getChunkNumber()); uploadTaskDetail.setChunkSize((int)uploadFileDto.getChunkSize()); uploadTaskDetail.setRelativePath(uploadFileDto.getRelativePath()); uploadTaskDetail.setTotalChunks(uploadFileDto.getTotalChunks()); uploadTaskDetail.setTotalSize((int)uploadFileDto.getTotalSize()); uploadTaskDetail.setIdentifier(uploadFileDto.getIdentifier()); uploadTaskDetailMapper.insert(uploadTaskDetail); } else if (UploadFileStatusEnum.FAIL.equals(uploadFileResult.getStatus())) { LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(UploadTaskDetail::getIdentifier, uploadFileDto.getIdentifier()); uploadTaskDetailMapper.delete(lambdaQueryWrapper); LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); lambdaUpdateWrapper.set(UploadTask::getUploadStatus, UploadFileStatusEnum.FAIL.getCode()) .eq(UploadTask::getIdentifier, uploadFileDto.getIdentifier()); uploadTaskMapper.update(null, lambdaUpdateWrapper); } } } private String formatChatset(String str) { if (str == null) { return ""; } if (Charset.forName("ISO-8859-1").newEncoder().canEncode(str)) { byte[] bytes = str.getBytes(StandardCharsets.ISO_8859_1); return new String(bytes, Charset.forName("GBK")); } return str; } @Override public void downloadFile(HttpServletResponse httpServletResponse, DownloadFileDTO downloadFileDTO) { DocFilePath userFile = docFilePathMapper.selectById(downloadFileDTO.getUserFileId()); if (userFile.getIsDir() == Constant.IS_NOT_DIR) { DocFile fileBean = docFileMapper.selectById(userFile.getFileId()); Downloader downloader = new LocalStorageDownloader(); if (downloader == null) { log.error("下载失败,文件存储类型不支持下载,storageType:{}", fileBean.getStorageType()); throw new DownloadException("下载失败"); } DownloadFile downloadFile = new DownloadFile(); downloadFile.setFileUrl(fileBean.getFileUrl()); httpServletResponse.setContentLengthLong(fileBean.getFileSize()); userStorageFlowService.updateSurplusFlowByUserId(downloadFileDTO.getUserToken(), fileBean.getFileSize()); downloader.download(httpServletResponse, downloadFile); } else { QiwenFile qiwenFile = new QiwenFile(userFile.getFilePath(), userFile.getFileName(), true); List userFileList = docFilePathMapper.selectUserFileByLikeRightFilePath(qiwenFile.getPath() ); List userFileIds = userFileList.stream().map(DocFilePath::getPathId).collect(Collectors.toList()); downloadUserFileList(httpServletResponse, userFile.getFilePath()+QiwenFile.separator, userFile.getFileName(), userFileIds, downloadFileDTO.getUserToken()); } } @Override public void downloadUserFileList(HttpServletResponse httpServletResponse, String filePath, String fileName, List userFileIds, String token) { String staticPath = UFOPUtils.getStaticPath(); String tempPath = staticPath + "temp" + File.separator; File tempDirFile = new File(tempPath); if (!tempDirFile.exists()) { tempDirFile.mkdirs(); } FileOutputStream f = null; try { f = new FileOutputStream(tempPath + fileName + ".zip"); } catch (FileNotFoundException e) { e.printStackTrace(); } CheckedOutputStream csum = new CheckedOutputStream(f, new Adler32()); ZipOutputStream zos = new ZipOutputStream(csum); BufferedOutputStream out = new BufferedOutputStream(zos); try { for (String userFileId : userFileIds) { DocFilePath userFile1 = docFilePathMapper.selectById(userFileId); if (userFile1.getIsDir() == Constant.IS_NOT_DIR) { DocFile fileBean = docFileMapper.selectById(userFile1.getFileId()); Downloader downloader = new LocalStorageDownloader(); if (downloader == null) { log.error("下载失败,文件存储类型不支持下载,storageType:{}", fileBean.getStorageType()); throw new UploadException("下载失败"); } DownloadFile downloadFile = new DownloadFile(); downloadFile.setFileUrl(fileBean.getFileUrl()); // String url = UFOPUtils.ENCRYPT_PATH + "/fileTransfer/encryptDownload"; // ResponseEntity responseEntity = restTemplate.exchange(url+"?userFileId=" + userFileId +"&userToken=" + token, HttpMethod.GET, null, byte[].class); // byte[] data; // if (responseEntity != null) { // data=responseEntity.getBody(); // } else { // data = new byte[0]; // } // //byte[] data =responseEntity.getBody(); // InputStream inputStream = new ByteArrayInputStream(data); InputStream inputStream = downloader.getInputStream(downloadFile); BufferedInputStream bis = new BufferedInputStream(inputStream); try { QiwenFile qiwenFile = new QiwenFile(userFile1.getFilePath(), userFile1.getFileName() + "." + userFile1.getExtendName(), false); zos.putNextEntry(new ZipEntry(qiwenFile.getPath().replaceFirst(filePath.replace("(","\\(").replace(")","\\)"), ""))); byte[] buffer = new byte[1024]; int i = bis.read(buffer); while (i != -1) { out.write(buffer, 0, i); i = bis.read(buffer); } } catch (IOException e) { log.error("" + e); e.printStackTrace(); } finally { IOUtils.closeQuietly(bis); try { out.flush(); } catch (IOException e) { e.printStackTrace(); } } } else { QiwenFile qiwenFile = new QiwenFile(userFile1.getFilePath(), userFile1.getFileName(), true); // 空文件夹的处理 zos.putNextEntry(new ZipEntry(qiwenFile.getPath().replaceFirst(filePath.replace("(","\\(").replace(")","\\)"),"") + QiwenFile.separator)); // 没有文件,不需要文件的copy zos.closeEntry(); } } } catch (Exception e) { log.error("压缩过程中出现异常:"+ e); } finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } String zipPath = ""; try { Downloader downloader = new LocalStorageDownloader(); DownloadFile downloadFile = new DownloadFile(); downloadFile.setFileUrl("temp" + File.separator + fileName + ".zip"); File tempFile = new File(UFOPUtils.getStaticPath() + downloadFile.getFileUrl()); httpServletResponse.setContentLengthLong(tempFile.length()); downloader.download(httpServletResponse, downloadFile); zipPath = UFOPUtils.getStaticPath() + "temp" + File.separator + fileName + ".zip"; } catch (Exception e) { //org.apache.catalina.connector.ClientAbortException: java.io.IOException: Connection reset by peer if (e.getMessage().contains("ClientAbortException")) { //该异常忽略不做处理 } else { log.error("下传zip文件出现异常:{}", e.getMessage()); } } finally { File file = new File(zipPath); if (file.exists()) { file.delete(); } } } @Override public void previewFile(HttpServletResponse httpServletResponse, PreviewDTO previewDTO) { DocFilePath userFile = docFilePathMapper.selectById(previewDTO.getUserFileId()); DocFile fileBean = docFileMapper.selectById(userFile.getFileId()); Previewer previewer = new LocalStoragePreviewer(new ThumbImage(150,150)); if (previewer == null) { log.error("预览失败,文件存储类型不支持预览,storageType:{}", fileBean.getStorageType()); throw new UploadException("预览失败"); } try { if ("true".equals(previewDTO.getIsMin())) { previewer.imageThumbnailPreview(httpServletResponse, fileBean.getFileUrl()); } else { previewer.imageOriginalPreview(httpServletResponse, fileBean.getFileUrl()); } } catch (Exception e){ //org.apache.catalina.connector.ClientAbortException: java.io.IOException: 你的主机中的软件中止了一个已建立的连接。 if (e.getMessage().contains("ClientAbortException")) { //该异常忽略不做处理 } else { log.error("预览文件出现异常:{}", e.getMessage()); } } } // // @Override // public void previewPictureFile(HttpServletResponse httpServletResponse, PreviewDTO previewDTO) { // byte[] bytesUrl = Base64.getDecoder().decode(previewDTO.getUrl()); // PictureFile pictureFile = new PictureFile(); // pictureFile.setFileUrl(new String(bytesUrl)); // pictureFile = pictureFileMapper.selectOne(new QueryWrapper<>(pictureFile)); // Previewer previewer = ufopFactory.getPreviewer(pictureFile.getStorageType()); // if (previewer == null) { // log.error("预览失败,文件存储类型不支持预览,storageType:{}", pictureFile.getStorageType()); // throw new UploadException("预览失败"); // } // PreviewFile previewFile = new PreviewFile(); // previewFile.setFileUrl(pictureFile.getFileUrl()); //// previewFile.setFileSize(pictureFile.getFileSize()); // try { // // String mime= MimeUtils.getMime(pictureFile.getExtendName()); // httpServletResponse.setHeader("Content-Type", mime); // // String fileName = pictureFile.getFileName() + "." + pictureFile.getExtendName(); // try { // fileName = new String(fileName.getBytes("utf-8"), "ISO-8859-1"); // } catch (UnsupportedEncodingException e) { // e.printStackTrace(); // } // // httpServletResponse.addHeader("Content-Disposition", "fileName=" + fileName);// 设置文件名 // // previewer.imageOriginalPreview(httpServletResponse, previewFile); // } catch (Exception e){ // //org.apache.catalina.connector.ClientAbortException: java.io.IOException: 你的主机中的软件中止了一个已建立的连接。 // if (e.getMessage().contains("ClientAbortException")) { // //该异常忽略不做处理 // } else { // log.error("预览文件出现异常:{}", e.getMessage()); // } // // } // } @Override public void deleteFile(DocFile fileBean) { Deleter deleter = null; deleter = new LocalStorageDeleter(); DeleteFile deleteFile = new DeleteFile(); deleteFile.setFileUrl(fileBean.getFileUrl()); deleter.delete(deleteFile); } // // @Override // public Long selectStorageSizeByUserId(Long userId){ // return userFileMapper.selectStorageSizeByUserId(userId); // } }