DocumentServiceImpl.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. package com.loan.system.service.Impl;
  2. import cn.hutool.core.bean.BeanUtil;
  3. import com.aliyun.oss.model.OSSObject;
  4. import com.loan.system.controller.wechat.OssFileController;
  5. import com.loan.system.domain.dto.BatchDownloadDTO;
  6. import com.loan.system.domain.dto.DocumentDTO;
  7. import com.loan.system.domain.dto.query.DocumentQueryDTO;
  8. import com.loan.system.domain.entity.Customer;
  9. import com.loan.system.domain.entity.Document;
  10. import com.loan.system.domain.enums.ExceptionEnum;
  11. import com.loan.system.domain.pojo.Result;
  12. import com.loan.system.domain.vo.CustomerVO;
  13. import com.loan.system.domain.vo.DocumentVO;
  14. import com.loan.system.domain.vo.LoanCaseSimpleVO;
  15. import com.loan.system.repository.DocumentRepository;
  16. import com.loan.system.service.CustomerService;
  17. import com.loan.system.service.DocumentService;
  18. import com.loan.system.service.LoanCaseService;
  19. import com.loan.system.service.LoanService;
  20. import com.loan.system.utils.ResultUtil;
  21. import lombok.RequiredArgsConstructor;
  22. import lombok.extern.slf4j.Slf4j;
  23. import org.apache.commons.io.FilenameUtils;
  24. import org.springframework.beans.factory.annotation.Autowired;
  25. import org.springframework.context.annotation.Lazy;
  26. import org.springframework.data.domain.Page;
  27. import org.springframework.data.domain.PageRequest;
  28. import org.springframework.data.domain.Pageable;
  29. import org.springframework.stereotype.Service;
  30. import org.springframework.util.ObjectUtils;
  31. import org.springframework.web.bind.annotation.RequestParam;
  32. import org.springframework.web.multipart.MultipartFile;
  33. import javax.servlet.http.HttpServletResponse;
  34. import java.io.IOException;
  35. import java.io.InputStream;
  36. import java.io.OutputStream;
  37. import java.net.URLEncoder;
  38. import java.time.LocalDateTime;
  39. import java.time.format.DateTimeFormatter;
  40. import java.util.*;
  41. import java.util.stream.Collectors;
  42. import java.util.zip.ZipEntry;
  43. import java.util.zip.ZipOutputStream;
  44. @Service
  45. @RequiredArgsConstructor
  46. @Slf4j
  47. public class DocumentServiceImpl implements DocumentService {
  48. private final DocumentRepository documentRepository;
  49. private final OssService ossService;
  50. Map<String, String> dictTypeMap = new HashMap<String, String>() {{
  51. put("idCard", "借款人身份证");
  52. put("customers1IdCard", "共同借款人1身份证");
  53. put("customers2IdCard", "共同借款人2身份证");
  54. put("householdRegister", "户口本照片");
  55. put("marriageCertificate", "婚姻证明");
  56. put("propertyCertificate", "房产证");
  57. put("ownershipCertificate", "产调证明");
  58. put("microCourtInquiry", "微法院查询");
  59. put("businessLicense", "营业执照");
  60. put("personalCredit", "个人征信");
  61. put("contract", "合同");
  62. put("receipt", "当票");
  63. put("otherCertificates", "他项权证");
  64. put("contractAttachment", "合同其他附件");
  65. put("otherAttachments", "其他附件");
  66. put("bankReceipt", "银行回单");
  67. put("settlementCertificate", "借款结清证明");
  68. put("evidenceCollectionConfirm", "押品入库证明");
  69. put("deliveryConfirm", "押品出库证明");
  70. }};
  71. @Override
  72. public List<DocumentVO> findByCaseId(Long caseId) {
  73. return BeanUtil.copyToList(documentRepository.findByCaseId(caseId), DocumentVO.class);
  74. }
  75. @Override
  76. public DocumentVO uploadFile(Document document) {
  77. return BeanUtil.copyProperties(documentRepository.save(document), DocumentVO.class);
  78. }
  79. @Override
  80. public Document findById(Long signId) {
  81. return documentRepository.findByDocumentIdAndIsDelete(signId, false);
  82. }
  83. @Override
  84. public void updateDocumentByCaseIdAndDicType(Long caseId, String dictType, DocumentDTO documentDTO) {
  85. Document document = BeanUtil.copyProperties(documentDTO, Document.class);
  86. document.setUpdateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
  87. documentRepository.updateByCaseIdAndDictType(caseId, dictType, document);
  88. }
  89. @Override
  90. public void deleteFileByCaseIdAndDictType(Long caseId, String fileType) {
  91. documentRepository.deleteFileByCaseIdAndDictType(caseId, fileType);
  92. }
  93. @Override
  94. public void deleteFileById(Long id) {
  95. documentRepository.deleteById(id);
  96. }
  97. @Override
  98. public void deleteFileByIds(List<Long> ids) {
  99. documentRepository.deleteByIds(ids);
  100. }
  101. @Override
  102. public Result findAll(Integer pageNum, Integer pageSize) {
  103. Pageable pageable = PageRequest.of(pageNum-1, pageSize);
  104. Page<Document> data = documentRepository.findAllAndIdDelete(false, pageable);
  105. return ResultUtil.success(data.getTotalElements(),BeanUtil.copyToList(data.getContent(), DocumentVO.class));
  106. }
  107. @Override
  108. public List<DocumentVO> findByFileTypesAndCaseId(List<String> fileTypes, Long caseId) {
  109. return BeanUtil.copyToList(documentRepository.findByFileTypesAndCaseIdAndIsDelete(fileTypes, caseId, false), DocumentVO.class);
  110. }
  111. @Override
  112. public Result uploadFileToOss(MultipartFile file, Long caseId, String fileType, Map<String, String> isDelete) {
  113. // 处理待删除的文件
  114. Iterator<Map.Entry<String, String>> iterator = isDelete.entrySet().iterator();
  115. while (iterator.hasNext()) {
  116. Map.Entry<String, String> entry = iterator.next();
  117. Long id = Long.parseLong(entry.getKey());
  118. Integer value = Integer.parseInt(entry.getValue());
  119. Document document = findById(id);
  120. if (ObjectUtils.isEmpty(document))
  121. break;
  122. if (value != 0) {
  123. log.info("删除文件: {}", id);
  124. deleteFileById(id);
  125. // 从OSS删除文件
  126. ossService.deleteFile(document.getFileName());
  127. }
  128. }
  129. if (file == null)
  130. return ResultUtil.success("success");
  131. String originalName = file.getOriginalFilename();
  132. String ext = FilenameUtils.getExtension(originalName).toLowerCase(Locale.ROOT);
  133. // 生成新的文件名
  134. String randomUUID = UUID.randomUUID().toString();
  135. String newFileName = String.format("%d/%s/%s.%s", caseId, fileType, randomUUID, ext);
  136. // 上传到OSS
  137. String fileUrl="";
  138. try {
  139. fileUrl = ossService.uploadFile(file.getInputStream(), newFileName);
  140. }catch (Exception e){
  141. return ResultUtil.error(ExceptionEnum.DIRECTORY_CREATE_ERROR);
  142. }
  143. Document document = new Document();
  144. document.setCaseId(caseId);
  145. document.setFileName(randomUUID+"."+ext);
  146. document.setOriginName(originalName);
  147. document.setFilePath(fileUrl); // 存储OSS文件URL
  148. document.setFileSize(file.getSize());
  149. document.setDocType(ext);
  150. document.setDictType(fileType);
  151. document.setIsDelete(false);
  152. document.setCreateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
  153. document.setUpdateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
  154. DocumentVO documentVO = uploadFile(document);
  155. return ResultUtil.success("上传成功", documentVO);
  156. }
  157. @Override
  158. public void downloadFileFromOss(Long caseId, String fileType, String filename, HttpServletResponse response) {
  159. try {
  160. String fullFileName = String.format("%d/%s/%s", caseId, fileType, filename);
  161. // 从OSS获取文件
  162. OSSObject ossObject = ossService.downloadFile(fullFileName);
  163. if (ossObject == null) {
  164. response.sendError(HttpServletResponse.SC_NOT_FOUND, "文件不存在");
  165. return;
  166. }
  167. // 设置响应头
  168. response.setContentType(ossObject.getObjectMetadata().getContentType());
  169. response.setContentLength((int) ossObject.getObjectMetadata().getContentLength());
  170. // 如果需要浏览器直接显示文件而不是下载,可以设置inline
  171. // 如果需要强制下载,可以设置attachment
  172. String disposition = "inline; filename=\"" + URLEncoder.encode(dictTypeMap.get(fileType) +"-"+ filename, "UTF-8") + "\"";
  173. response.setHeader("Content-Disposition", disposition);
  174. // 将文件内容写入响应流
  175. try (InputStream inputStream = ossObject.getObjectContent();
  176. OutputStream outputStream = response.getOutputStream()) {
  177. byte[] buffer = new byte[8192];
  178. int bytesRead;
  179. while ((bytesRead = inputStream.read(buffer)) != -1) {
  180. outputStream.write(buffer, 0, bytesRead);
  181. }
  182. outputStream.flush();
  183. }
  184. } catch (Exception e) {
  185. try {
  186. response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "文件读取失败: " + e.getMessage());
  187. } catch (IOException ioException) {
  188. // 处理发送错误响应时的异常
  189. }
  190. }
  191. }
  192. @Override
  193. public void batchDownloadFilesFromOss(BatchDownloadDTO batchDownloadDTO, HttpServletResponse response) throws IOException{
  194. List<DocumentDTO> documentDTOList = batchDownloadDTO.getDocumentDTOList();
  195. // 设置响应头
  196. String zipFilename = "批量下载_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + ".zip";
  197. response.setContentType("application/zip");
  198. response.setCharacterEncoding("UTF-8");
  199. response.setHeader("Content-Disposition",
  200. "attachment; filename=\"" + URLEncoder.encode(zipFilename, "UTF-8") + "\"");
  201. try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
  202. byte[] buffer = new byte[8192];
  203. int bytesRead;
  204. for (int i = 0; i < documentDTOList.size(); i++) {
  205. DocumentDTO documentDTO = documentDTOList.get(i);
  206. String filename = documentDTO.getFileName();
  207. Long caseId = documentDTO.getCaseId();
  208. String fileType = documentDTO.getDictType();
  209. try {
  210. String fullFileName = String.format("%d/%s/%s", caseId, fileType, filename);
  211. OSSObject ossObject = ossService.downloadFile(fullFileName);
  212. if (ossObject == null) {
  213. // 文件不存在,可以记录日志或添加错误文件到ZIP
  214. continue;
  215. }
  216. // 创建ZIP条目
  217. ZipEntry zipEntry = new ZipEntry(dictTypeMap.get(fileType) +"-"+ documentDTO.getOriginName());
  218. // 可选:设置条目的创建时间
  219. zipEntry.setTime(ossObject.getObjectMetadata().getLastModified().getTime());
  220. zipOut.putNextEntry(zipEntry);
  221. // 将文件内容写入ZIP
  222. try (InputStream inputStream = ossObject.getObjectContent()) {
  223. while ((bytesRead = inputStream.read(buffer)) != -1) {
  224. zipOut.write(buffer, 0, bytesRead);
  225. }
  226. }
  227. zipOut.closeEntry();
  228. } catch (Exception e) {
  229. // 记录单个文件下载失败,继续处理其他文件
  230. // 可以在这里添加错误日志
  231. e.printStackTrace();
  232. }
  233. }
  234. zipOut.finish();
  235. zipOut.flush();
  236. } catch (Exception e) {
  237. try {
  238. response.reset(); // 重置响应
  239. response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
  240. "打包文件失败: " + e.getMessage());
  241. } catch (IOException ioException) {
  242. // 处理发送错误响应时的异常
  243. }
  244. }
  245. }
  246. @Override
  247. public Result queryFiles(Integer pageNum, Integer pageSize, DocumentQueryDTO documentQueryDTO) {
  248. Pageable pageable = PageRequest.of(pageNum-1, pageSize);
  249. Page<Document> data = documentRepository.findByQuery(documentQueryDTO, pageable);
  250. return ResultUtil.success(data.getTotalElements(), data.getContent());
  251. }
  252. }