package jnpf.dmsService; import feign.Response; import jnpf.base.ActionResult; import jnpf.base.ActionResultCode; import jnpf.dmsEntity.permission.enums.DmsResourceType; import jnpf.dmsEntity.preview.form.DmsFilePreviewTicketRequest; import jnpf.dmsEntity.preview.vo.DmsFilePageCountVO; import jnpf.dmsEntity.preview.vo.DmsFilePreviewTicketVO; import jnpf.dmsService.file.DmsFileContentApi; import jnpf.onlyoffice.DmsPageCountApi; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.Locale; import java.util.UUID; @Service @RequiredArgsConstructor public class DmsFilePageCountService { private final DmsFilePreviewService previewService; private final DmsFileContentApi fileContentApi; private final DmsDocumentPageCountService documentPageCountService; private final DmsPageCountApi onlyOfficePageCountApi; public DmsFilePageCountVO getPageCount(UUID fileVersionId) throws IOException { DmsFilePreviewTicketVO ticket = createReadTicket(fileVersionId); int pageCount = readPageCount(fileVersionId, ticket); DmsFilePageCountVO result = new DmsFilePageCountVO(); result.setFileVersionId(fileVersionId); result.setFileName(ticket.getFileName()); result.setPageCount(pageCount); return result; } private int readPageCount(UUID fileVersionId, DmsFilePreviewTicketVO ticket) throws IOException { String extension = suffix(ticket.getFileName()); if (".doc".equals(extension) || ".docx".equals(extension)) { ActionResult result = onlyOfficePageCountApi.getPageCount( fileVersionId, ticket.getAccessTicket()); if (result == null || !ActionResultCode.SUCCESS.getCode().equals(result.getCode()) || result.getData() == null || result.getData() <= 0) { throw new IOException("OnlyOffice 页数查询失败,请稍后重试"); } return result.getData(); } if (!".pdf".equals(extension)) { throw new IOException("页数查询仅支持 doc、docx、pdf 文件"); } Path temporaryFile = download(fileVersionId, ticket); try { return documentPageCountService.getPageCount(temporaryFile, ticket.getFileName()); } finally { Files.deleteIfExists(temporaryFile); } } private DmsFilePreviewTicketVO createReadTicket(UUID fileVersionId) { DmsFilePreviewTicketRequest request = new DmsFilePreviewTicketRequest(); request.setResourceType(DmsResourceType.FILE_VERSION); request.setResourceId(fileVersionId); request.setOperationId(UUID.randomUUID()); return previewService.createTicket(request); } private Path download(UUID fileVersionId, DmsFilePreviewTicketVO ticket) throws IOException { Response response = fileContentApi.stream(fileVersionId, ticket.getAccessTicket()); if (response == null || response.status() < 200 || response.status() >= 300 || response.body() == null) { if (response != null) { response.close(); } throw new IOException("文件服务读取失败"); } Path target = Files.createTempFile("dms-page-count-", suffix(ticket.getFileName())); try { copy(response, target); return target; } catch (IOException exception) { Files.deleteIfExists(target); throw exception; } } private void copy(Response response, Path target) throws IOException { byte[] buffer = new byte[64 * 1024]; try (Response ignored = response; InputStream input = response.body().asInputStream(); OutputStream output = Files.newOutputStream(target)) { int read; while ((read = input.read(buffer)) >= 0) { output.write(buffer, 0, read); } } } private String suffix(String fileName) { int separator = fileName == null ? -1 : fileName.lastIndexOf('.'); if (separator < 0) { return ".bin"; } String value = fileName.substring(separator).toLowerCase(Locale.ROOT); return value.matches("\\.[a-z0-9]{1,10}") ? value : ".bin"; } }