研究了很多网上的文章,实际上并没有什么作用,尤其是后端对文档的处理,网上的都是开源的jar包处理,转换后要么乱码,要么样式乱,根本达不到自己想要的效果,想过对接wps平台;没想到接口收费那么贵,1页/0.1元,那随便一个文档转换下来100页还不得10元吗?不现实;
还是老外开发的靠谱,最后对接了这个网站,100页就0.3-0.5元的成本而已,而且效果非常好
先看效果:pdf-wrod-excel相互转换

对接的文档转换api: https://cloudconvert.com/pdf-to-docx,如果英文不太好不容易理解的,也可以直接对接:pdf-wrod-excel相互转换API接口
流程:前端上传文档file流给后端,后端调用第三方接口直接处理即可,第三方会返回文档链接
java代码如下
java
package com.ruoyi.basicTool.convertDoc;
import com.cloudconvert.client.CloudConvertClient;
import com.cloudconvert.client.setttings.StringSettingsProvider;
import com.cloudconvert.dto.request.*;
import com.cloudconvert.dto.response.JobResponse;
import com.cloudconvert.dto.response.TaskResponse;
import com.google.common.collect.ImmutableMap;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.OrderUtils;
import com.ruoyi.common.utils.SecurityAppUtils;
import com.ruoyi.tmp.domain.ConvertOrder;
import com.ruoyi.tmp.mapper.ConvertOrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Map;
/**
* pdf转word
* https://cloudconvert.com/dashboard#
*/
@Component
public class DocConvertUtils {
private static String API_KEY="xxxxxxxxxxxxxxxxxxxxxx";
private static String API_SECRET="xxxxxxxxx";
@Autowired
private ConvertOrderMapper convertOrderMapper;
/**
* 文件转换
* @param filePath
* @param outputFileType
* @param file
* @return
*/
public String fileConvert(String filePath, String outputFileType, MultipartFile file){
Map<String, String> fileMap=null;
try {
final CloudConvertClient cloudConvertClient = new CloudConvertClient(new StringSettingsProvider(API_KEY, API_SECRET,false));
final JobResponse createJobResponse = cloudConvertClient.jobs().create(
ImmutableMap.of(
"import-my-file",
new UrlImportRequest()
.setUrl(filePath),
"convert-my-file",
new ConvertFilesTaskRequest()
.setInput("import-my-file")
.setOutputFormat(outputFileType),
"export-my-file",
new UrlExportRequest()
.setInput("convert-my-file")
)
).getBody();
final JobResponse waitJobResponse =
cloudConvertClient.jobs().wait(createJobResponse.getId()).getBody();
final TaskResponse exportUrlTask =
waitJobResponse.getTasks().stream().filter(
taskResponse -> taskResponse.getName().equals("export-my-file")
).findFirst().get();
/**
* [{
* "filename": "04859c73839b444fad682ebb73118813.docx",
* "size": "106697",
* "url": "https://eu-central.storage.cloudconvert.com/tasks/90288c3d-16bb-4917-9fc0-1a6f63b2db04/04859c73839b444fad682ebb73118813.docx?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=cloudconvert-production%2F20260109%2Ffra%2Fs3%2Faws4_request&X-Amz-Date=20260109T064326Z&X-Amz-Expires=86400&X-Amz-Signature=e93bdf7bba2444294f5408958ad7a1bdc823f4bb86481ed1bdfb64db60730d3d&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%2204859c73839b444fad682ebb73118813.docx%22&response-content-type=application%2Fvnd.openxmlformats-officedocument.wordprocessingml.document&x-id=GetObject"
* }]
*/
List<Map<String, String>> files = exportUrlTask.getResult().getFiles();
final String exportUrl =files.get(0).get("url");
fileMap=files.get(0);
fileMap.put("jobId",createJobResponse.getId());
fileMap.put("taskId",exportUrlTask.getId());
return exportUrl;
}catch (Exception e){
e.printStackTrace();
}finally {
//保存操作日志
this.saveConvertOrder(filePath,file,fileMap);
}
throw new RuntimeException("服务正忙!请稍后再试!");
}
/**
* 开放平台 / 无登录上下文:仅调用 CloudConvert,不写 convert_order(避免 SecurityAppUtils 依赖)。
* sourceUrl 须为 CloudConvert 可拉取的公网 http(s) 地址。
*/
public String convertPublicUrlToFormat(String sourceUrl, String outputFileType) {
if (sourceUrl == null || sourceUrl.trim().isEmpty()) {
throw new IllegalArgumentException("源文件链接不能为空");
}
if (outputFileType == null || outputFileType.trim().isEmpty()) {
throw new IllegalArgumentException("目标格式不能为空");
}
try {
final CloudConvertClient cloudConvertClient = new CloudConvertClient(
new StringSettingsProvider(API_KEY, API_SECRET, false));
final JobResponse createJobResponse = cloudConvertClient.jobs().create(
ImmutableMap.of(
"import-my-file",
new UrlImportRequest().setUrl(sourceUrl.trim()),
"convert-my-file",
new ConvertFilesTaskRequest()
.setInput("import-my-file")
.setOutputFormat(outputFileType.trim()),
"export-my-file",
new UrlExportRequest().setInput("convert-my-file")
)
).getBody();
final JobResponse waitJobResponse =
cloudConvertClient.jobs().wait(createJobResponse.getId()).getBody();
final TaskResponse exportUrlTask =
waitJobResponse.getTasks().stream().filter(
taskResponse -> taskResponse.getName().equals("export-my-file")
).findFirst().get();
List<Map<String, String>> files = exportUrlTask.getResult().getFiles();
return files.get(0).get("url");
} catch (Exception e) {
e.printStackTrace();
}
throw new RuntimeException("服务正忙!请稍后再试!");
}
/**
* pdf压缩
* @param filePath
* @param outputFileType
* @param file
* @return
*/
public String compressPdf(String filePath, String outputFileType, MultipartFile file){
Map<String, String> fileMap=null;
try {
final CloudConvertClient cloudConvertClient = new CloudConvertClient(new StringSettingsProvider(API_KEY, API_SECRET,false));
final JobResponse createJobResponse = cloudConvertClient.jobs().create(
ImmutableMap.of(
"import-my-file",
new UrlImportRequest()
.setUrl(filePath),
"compress-my-file",
new ConvertFilesTaskRequest()
.setInput("import-my-file")
.setOutputFormat(outputFileType),
"export-my-file",
new UrlExportRequest()
.setInput("compress-my-file")
)
).getBody();
final JobResponse waitJobResponse =
cloudConvertClient.jobs().wait(createJobResponse.getId()).getBody();
final TaskResponse exportUrlTask =
waitJobResponse.getTasks().stream().filter(
taskResponse -> taskResponse.getName().equals("export-my-file")
).findFirst().get();
/**
* [{
* "filename": "04859c73839b444fad682ebb73118813.docx",
* "size": "106697",
* "url": "https://eu-central.storage.cloudconvert.com/tasks/90288c3d-16bb-4917-9fc0-1a6f63b2db04/04859c73839b444fad682ebb73118813.docx?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=cloudconvert-production%2F20260109%2Ffra%2Fs3%2Faws4_request&X-Amz-Date=20260109T064326Z&X-Amz-Expires=86400&X-Amz-Signature=e93bdf7bba2444294f5408958ad7a1bdc823f4bb86481ed1bdfb64db60730d3d&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%2204859c73839b444fad682ebb73118813.docx%22&response-content-type=application%2Fvnd.openxmlformats-officedocument.wordprocessingml.document&x-id=GetObject"
* }]
*/
List<Map<String, String>> files = exportUrlTask.getResult().getFiles();
final String exportUrl =files.get(0).get("url");
fileMap=files.get(0);
fileMap.put("jobId",createJobResponse.getId());
fileMap.put("taskId",exportUrlTask.getId());
return exportUrl;
}catch (Exception e){
e.printStackTrace();
}finally {
//保存操作日志
this.saveConvertOrder(filePath,file,fileMap);
}
throw new RuntimeException("服务正忙!请稍后再试!");
}
private void saveConvertOrder(String fileUrl,MultipartFile file,Map<String, String> fileMap){
ConvertOrder order=new ConvertOrder();
order.setOrderId(OrderUtils.getOrderNumTimeMillis());
order.setUserId(SecurityAppUtils.getUserId());
order.setWxOpenId(SecurityAppUtils.getAppLoginUser().getAppUser().getWxOpenId());
order.setWxOpenId(SecurityAppUtils.getAppLoginUser().getAppUser().getMobilePhoneNo());
//暂时使用的临时文件,上传后就删除了
//order.setOriginalUrl(filePath);
order.setOriginalName(file.getOriginalFilename());
order.setOriginalSuffix(file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")));
order.setOriginalSize(file.getSize());
order.setConvertUrl(fileUrl);
order.setConvertStatus(2);
if(fileMap!=null){
order.setConvertName(fileMap.get("filename"));
order.setConvertSuffix(fileMap.get("filename").substring(fileMap.get("filename").lastIndexOf(".")));
order.setConvertSize(Integer.parseInt(fileMap.get("size")));
order.setConvertStatus(1);
order.setConvertJobId(fileMap.get("jobId"));
order.setConvertTaskId(fileMap.get("taskId"));
order.setOrderStatus(4);
}
order.setCreateTime(DateUtils.getNowDate());
convertOrderMapper.insertConvertOrder(order);
}
}