天就给大家介绍几款可以实现 PDF 转换 Word 格式的免费在线工具,收藏了它们,你不再需要下载安装,只需一个可以上网的浏览器,把PDF文档上传到网站,马上就能转换出 doc 或 docx、rtf 等 Office 格式的文档了,相当的方便实用!如果这篇文章能帮上你的忙,或你的朋友有类似的需求,欢迎大家用各种方式扩散~~~
网站介绍
一.迅捷在线转换
传送门:http://app.xunjiepdf.com/
迅捷在线pdf转word转换器免费版为您提供将PDF转换成WORD,word转换成pdf,ppt转换成pdf的免费在线转换服务;是一款完全免费的在线转换工具,在线免费完成PDF与word的转换,在线免费完成图片与PDF的转换,在线免费完成PDF与TXT等的转换,功能齐全,亲测有用!!唯一的的缺点就是文档限制2M。
1.主界面
2.文档转换,功能齐全
3.文档处理
4.在线PS等等
二、office converter
传送门:https://cn.office-converter.com/Convert-to-Word
这个免费在线转换器不只是一个在线文档转换器, 在线文件转换器。比如快速转换 PDF, Docx, Doc, Txt, ODT, SXW, RTF, WPD, HTML file formats转换成Doc格式. 比如包括PDF转换成Doc, Docx转换成Doc,Doc转换成Doc, Txt转换成Doc, ODT转换成Doc, SXW转换成Doc, RTF转换成Doc, WPD转换成Doc, HTML转换成Doc, PDF转换成Docx, Docx转换成Docx, Doc转换成Docx, Txt转换成Docx, ODT转换成Docx, SXW转换成Docx, RTF转换成Docx, WPD转换成Docx, HTML转换成Docx等.
传送门:https://www.addpdf.cn/ppt-to-pdf
免费在线完成PDF转Word,免费在线完成Word转PDF,免费在线完成PDF转JPG。功能是少了点,但对文档大小限制要大点(10M),也挺实用的。
四、LightPDF、smallPDF等等
最重要的一点
有了上面的这些在线PDF转换Word工具,基本已经能满足大部分人的需求了。不过,因为这些网站都需要你上传PDF文档到它们的服务器之后才能为你转换,所以如果你的PDF有比较重要且不希望被公开的信息,最好寻求别的途径进行转换。或者使用迅捷在线转换,也就是第一个,这个文档是有安全性的,自己可以选择是否公开,也可以直接转换后去把转换记录删除掉即可。
多时候在工作中会碰到完全由前端导出word文件的需求,因此特地记录一下比较常用的几种方式。
该方法提供一个word模板文件,数据通过参数替换的方式传入word文件中,灵活性较差,适用于简单的文件导出。需要依赖:docxtemplater、file-saver、jszip-utils、pizzip。
import Docxtemplater from "docxtemplater";
import { saveAs } from "file-saver";
import JSZipUtils from "jszip-utils";
import PizZip from "pizzip";
export function downloadWithTemplate(path, data, fileName) {
JSZipUtils.getBinaryContent(path, (error, content)=> {
if (error) throw error;
const zip=new PizZip(content);
const doc=new Docxtemplater().loadZip(zip);
doc.setData({
...data.form,
// 循环项参数
list: data.list,
outsideList: data.outsideList,
});
try {
doc.render();
} catch (error) {
const e={
message: error.message,
name: error.name,
stack: error.stack,
properties: error.properties,
};
ElMessage.error("文件格式有误!");
throw error;
}
const out=doc.getZip().generate({
type: "blob",
mimeType:
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
});
saveAs(out, fileName);
});
}
let data={
form: {
title: "这是word标题",
test: "这是表单1的数据",
test1: "111",
test2: 222,
test3: 333,
},
outsideList: [
{
list: [
{
index: 0,
table: "表格第一项",
table1: "表格第二项",
table2: "表格第三项",
},
{
index: 1,
table: "表格第一项",
table1: "表格第二项",
table2: "表格第三项",
},
],
},
{
list: [
{
index: 0,
table: "表格第一项",
table1: "表格第二项",
table2: "表格第三项",
},
{
index: 1,
table: "表格第一项",
table1: "表格第二项",
table2: "表格第三项",
},
],
},
],
};
downloadWithTemplate("template.docx", data, "模板word.docx")
调用downloadWithTemplate方法即可导出如下文件:
注: 上述方法中的path参数为你在vue项目中存放公共文件的位置,在vue2中为static文件夹下,在vue3中为public文件夹下。
顾名思义,这个方法就是将我们在页面上书写的html代码直接转换成word文件,这也是我最推荐的一种方法,因为大部分的样式可控,且毕竟是我们较为熟悉的方式。需要插件: html-docx-js-typescript、file-saver。
import { saveAs } from "file-saver";
import { asBlob } from "html-docx-js-typescript";
export function downloadWordWithHtmlString(html, name) {
let htmlString=`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
${html}
</body>
</html>
`;
asBlob(htmlString).then((data)=> {
saveAs(data, `${name}.docx`);
});
}
`
使用案例:
<div ref="word">
<h3 style="text-align: center">word标题</h3>
<table
border="1"
cellspacing="0"
width="600"
style="font-size: 12px; color: #000; text-align: center"
>
<tr height="50">
<td width="100">1111</td>
<td widt="200" colspan="2">合并单元格</td>
<td width="300">最长的一项</td>
</tr>
<tr height="100">
<td width="100">222</td>
<td width="100">222</td>
<td width="100">222</td>
<td width="100">222</td>
</tr>
</table>
<table width="600" border="1" cellspacing="0">
<tr height="50">
<td width="100">1111</td>
<td rowspan="3">合并包括此行在内的下面三行</td>
</tr>
<tr height="100">
<td>222</td>
</tr>
<tr height="300">
<td>3333</td>
</tr>
<tr>
<td>50</td>
</tr>
</table>
</div>
let word=ref(null);
downloadWordWithHtmlString(word.value.innerHTML, 'html字符串word.docx');
生成的word文件可以看到效果和在网页中的html代码一样:
另外需要注意的是,若是需要在word中添加分页符,在需要分页的内容处添加CSS属性page-break-before即可。此时在浏览器上打印出innerHTML值会发现:
mdn上介绍page-break-before属性已经被break-before属性替代,但是经过我实际测试发现当html字符串是page-break: always时生成的word文件没有分页效果,反而是将其替换回page-break-before后实现了分页效果。若有大神知道这是什么问题还望不吝赐教。 因此需要在downloadWordWithHtmlString方法中添加一句正则: htmlString=htmlString.replace( /break-(after|before): page/g, "page-break-: always;" );,此时就能实现分页效果。
第二种方法有个很致命的问题就是它无法在生成的word文件中添加图片页眉,我搜遍了npm也只找到一个能添加文字页眉的插件: html-docx-ts。要想实现这个需求,就需要用到docx插件。 docx官网的介绍是"Easily generate and modify .docx files with JS/TS. Works for Node and on the Browser.",意味着是一个专门用于生成word和修改word的文件。该插件就需要一个一个去配置你要生成的项,然后组合成一个word。一个简单的案例是:
import {
Document,
Paragraph,
Header,
TextRun,
Table,
TableRow,
TableCell,
WidthType,
Packer,
} from "docx";
import { saveAs } from "file-saver";
const document=new Document({
sections: [
{
headers: {
default: new Header({
children: [new Paragraph("我是页眉")],
}),
},
children: [
new Paragraph({
children: [
new TextRun({
text: "我是文字内容",
size: 16,
bold: true,
}),
],
}),
new Table({
columnWidths: [1500, 7500],
rows: [
new TableRow({
children: [
new TableCell({
width: {
size: 1500,
type: WidthType.DXA,
},
children: [
new Paragraph({
alignment: "center",
children: [
new TextRun({
text: "测试",
size: 24,
font: {
name: "楷体",
},
}),
],
}),
],
}),
],
}),
],
}),
],
},
],
});
Packer.toBlob(document).then((blob)=> {
saveAs(blob, "test.docx");
});
导出的word文件形式为
下面是我个人总结的比较常见能用到的功能和配置项:
// 导出文字
1.new Paragraph(text) -> 默认字体样式: 宋体,五号字
2.new Paragraph({
children: [
new TextRun({
text: "我是文字内容",
size: 16, // 对应word中的字体大小8
bold: true, // 是否加粗
underline: {
type: UnderlineType.SINGLE,
color: "#2e32ee",
}, // 下划线类型及颜色
font: {
name: "仿宋", // 只要是word中有的字体类型都可以生效
},
}),
],
indent: {
left: 100,
}, // 离左边距离 类似于margin-left
spacing: {
before: 150,
after: 200,
}, // 离上边和下边的距离 类似于margin-top/bottom
alignment: "center", // 对齐方式
pageBreakBefore: true, // 是否在这段文字前加入分页符
})
// 导出表格
new Table({
columnWidths: [1500, 7500], // 表示单行有几项,总宽度是9000,对应宽度;
rows: [
new TableRow({
children: [
new TableCell({
width: {
size: 1500, // 需与columnWidths的第一项对应
type: WidthType.DXA, // 官网的介绍是Value is in twentieths of a point
// 因为表格的总宽度是以twips(每英寸的1/20)为单位进行计算的
},
children: [
new Paragraph({
alignment: "center",
children: [
new TextRun({
text: "测试",
size: 24,
font: {
name: "楷体",
},
}),
],
}),
],
}),
new TableCell({
width: {
size: 7500,
type: WidthType.DXA,
},
children: [
new Paragraph('ccc'),
],
margins: {
top: 500,
bottom: 500,
left: 500
} // 类似于单元格内容的padding
}),
],
}),
],
})
// 导出图片
new Paragraph({
children: [
new ImageRun({
data: "base64", // 图片需转成base64的形式
transformation: {
width: 100,
height: 30,
}, // 图片宽高
}),
],
})
// 设置页眉页脚
headers: {
default: new Header({
children: [new Paragraph("我是页眉")],
}),
},
footers: {
default: new Footer({
children: [new Paragraph("我是页脚")],
}),
}
下面是一个完整的使用案例:
const document=new Document({
sections: [
{
headers: {
default: new Header({
children: [
new Paragraph({
children: [
new ImageRun({
data: "data:image/jpeg;base64,...",
transformation: {
width: 150,
height: 150,
},
}),
],
}),
],
}),
},
footers: {
default: new Footer({
children: [new Paragraph("我是页脚")],
}),
},
children: [
new Paragraph("第一行直接默认形式"),
new Paragraph({
children: [
new TextRun({
text: "下一页",
}),
],
pageBreakBefore: true,
}),
new Table({
columnWidths: [1500, 7500],
rows: [
new TableRow({
children: [
new TableCell({
width: {
size: 1500,
type: WidthType.DXA,
},
children: [
new Paragraph({
alignment: "center",
children: [
new TextRun({
text: "测试",
size: 24,
font: {
name: "楷体",
},
}),
],
}),
],
}),
new TableCell({
width: {
size: 7500,
type: WidthType.DXA,
},
children: [
new Paragraph({
children: [
new ImageRun({
data: "data:image/jpeg;base64,...",
transformation: {
width: 150,
height: 150,
},
}),
],
}),
],
margins: {
top: 500,
bottom: 500,
left: 500,
},
}),
],
}),
],
}),
],
},
],
});
Packer.toBlob(document).then((blob)=> {
saveAs(blob, "test.docx");
});
此时导出的word文件如下:
若是以上内容有任何有问题的地方或是更好的解决方案,还望各位大神不吝赐教!
实现文档在线预览的方式除了上篇文章 文档在线预览新版(一)通过将文件转成图片实现在线预览功能说的将文档转成图片的实现方式外,还有转成pdf,前端通过pdf.js、pdfobject.js等插件来实现在线预览,以及本文将要说到的将文档转成html的方式来实现在线预览。
以下代码分别提供基于aspose、pdfbox、spire来实现来实现txt、word、pdf、ppt、word等文件转图片的需求。
Aspose 是一家致力于.Net ,Java,SharePoint,JasperReports和SSRS组件的提供商,数十个国家的数千机构都有用过aspose组件,创建、编辑、转换或渲染 Office、OpenOffice、PDF、图像、ZIP、CAD、XPS、EPS、PSD 和更多文件格式。注意aspose是商用组件,未经授权导出文件里面都是是水印(尊重版权,远离破解版)。
需要在项目的pom文件里添加如下依赖
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>23.1</version>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-pdf</artifactId>
<version>23.1</version>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-cells</artifactId>
<version>23.1</version>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-slides</artifactId>
<version>23.1</version>
</dependency>
因为aspose和spire虽然好用,但是都是是商用组件,所以这里也提供使用开源库操作的方式的方式。
POI是Apache软件基金会用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程序对Microsoft Office格式档案读和写的功能。
Apache PDFBox是一个开源Java库,支持PDF文档的开发和转换。 使用此库,您可以开发用于创建,转换和操作PDF文档的Java程序。
需要在项目的pom文件里添加如下依赖
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-excelant</artifactId>
<version>5.2.0</version>
</dependency>
spire一款专业的Office编程组件,涵盖了对Word、Excel、PPT、PDF等文件的读写、编辑、查看功能。spire提供免费版本,但是存在只能导出前3页以及只能导出前500行的限制,只要达到其一就会触发限制。需要超出前3页以及只能导出前500行的限制的这需要购买付费版(尊重版权,远离破解版)。这里使用免费版进行演示。
spire在添加pom之前还得先添加maven仓库来源
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
接着在项目的pom文件里添加如下依赖
免费版:
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.office.free</artifactId>
<version>5.3.1</version>
</dependency>
付费版版:
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.office</artifactId>
<version>5.3.1</version>
</dependency>
public static String wordToHtmlStr(String wordPath) {
try {
Document doc=new Document(wordPath); // Address是将要被转化的word文档
String htmlStr=doc.toString();
return htmlStr;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
验证结果:
public String wordToHtmlStr(String wordPath) throws TransformerException, IOException, ParserConfigurationException {
String htmlStr=null;
String ext=wordPath.substring(wordPath.lastIndexOf("."));
if (ext.equals(".docx")) {
htmlStr=word2007ToHtmlStr(wordPath);
} else if (ext.equals(".doc")){
htmlStr=word2003ToHtmlStr(wordPath);
} else {
throw new RuntimeException("文件格式不正确");
}
return htmlStr;
}
public String word2007ToHtmlStr(String wordPath) throws IOException {
// 使用内存输出流
try(ByteArrayOutputStream out=new ByteArrayOutputStream()){
word2007ToHtmlOutputStream(wordPath, out);
return out.toString();
}
}
private void word2007ToHtmlOutputStream(String wordPath,OutputStream out) throws IOException {
ZipSecureFile.setMinInflateRatio(-1.0d);
InputStream in=Files.newInputStream(Paths.get(wordPath));
XWPFDocument document=new XWPFDocument(in);
XHTMLOptions options=XHTMLOptions.create().setIgnoreStylesIfUnused(false).setImageManager(new Base64EmbedImgManager());
// 使用内存输出流
XHTMLConverter.getInstance().convert(document, out, options);
}
private String word2003ToHtmlStr(String wordPath) throws TransformerException, IOException, ParserConfigurationException {
org.w3c.dom.Document htmlDocument=word2003ToHtmlDocument(wordPath);
// Transform document to string
StringWriter writer=new StringWriter();
TransformerFactory tf=TransformerFactory.newInstance();
Transformer transformer=tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "html");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.transform(new DOMSource(htmlDocument), new StreamResult(writer));
return writer.toString();
}
private org.w3c.dom.Document word2003ToHtmlDocument(String wordPath) throws IOException, ParserConfigurationException {
InputStream input=Files.newInputStream(Paths.get(wordPath));
HWPFDocument wordDocument=new HWPFDocument(input);
WordToHtmlConverter wordToHtmlConverter=new WordToHtmlConverter(
DocumentBuilderFactory.newInstance().newDocumentBuilder()
.newDocument());
wordToHtmlConverter.setPicturesManager((content, pictureType, suggestedName, widthInches, heightInches) -> {
System.out.println(pictureType);
if (PictureType.UNKNOWN.equals(pictureType)) {
return null;
}
BufferedImage bufferedImage=ImgUtil.toImage(content);
String base64Img=ImgUtil.toBase64(bufferedImage, pictureType.getExtension());
// 带图片的word,则将图片转为base64编码,保存在一个页面中
StringBuilder sb=(new StringBuilder(base64Img.length() + "data:;base64,".length()).append("data:;base64,").append(base64Img));
return sb.toString();
});
// 解析word文档
wordToHtmlConverter.processDocument(wordDocument);
return wordToHtmlConverter.getDocument();
}
public String wordToHtmlStr(String wordPath) throws IOException {
try(ByteArrayOutputStream outputStream=new ByteArrayOutputStream()) {
Document document=new Document();
document.loadFromFile(wordPath);
document.saveToFile(outputStream, FileFormat.Html);
return outputStream.toString();
}
}
public static String pdfToHtmlStr(String pdfPath) throws IOException, ParserConfigurationException {
PDDocument document=PDDocument.load(new File(pdfPath));
Writer writer=new StringWriter();
new PDFDomTree().writeText(document, writer);
writer.close();
document.close();
return writer.toString();
}
验证结果:
public String pdfToHtmlStr(String pdfPath) throws IOException, ParserConfigurationException {
PDDocument document=PDDocument.load(new File(pdfPath));
Writer writer=new StringWriter();
new PDFDomTree().writeText(document, writer);
writer.close();
document.close();
return writer.toString();
}
public String pdfToHtmlStr(String pdfPath) throws IOException, ParserConfigurationException {
try(ByteArrayOutputStream outputStream=new ByteArrayOutputStream()) {
PdfDocument pdf=new PdfDocument();
pdf.loadFromFile(pdfPath);
return outputStream.toString();
}
}
public static String excelToHtmlStr(String excelPath) throws Exception {
FileInputStream fileInputStream=new FileInputStream(excelPath);
Workbook workbook=new XSSFWorkbook(fileInputStream);
DataFormatter dataFormatter=new DataFormatter();
FormulaEvaluator formulaEvaluator=workbook.getCreationHelper().createFormulaEvaluator();
Sheet sheet=workbook.getSheetAt(0);
StringBuilder htmlStringBuilder=new StringBuilder();
htmlStringBuilder.append("<html><head><title>Excel to HTML using Java and POI library</title>");
htmlStringBuilder.append("<style>table, th, td { border: 1px solid black; }</style>");
htmlStringBuilder.append("</head><body><table>");
for (Row row : sheet) {
htmlStringBuilder.append("<tr>");
for (Cell cell : row) {
CellType cellType=cell.getCellType();
if (cellType==CellType.FORMULA) {
formulaEvaluator.evaluateFormulaCell(cell);
cellType=cell.getCachedFormulaResultType();
}
String cellValue=dataFormatter.formatCellValue(cell, formulaEvaluator);
htmlStringBuilder.append("<td>").append(cellValue).append("</td>");
}
htmlStringBuilder.append("</tr>");
}
htmlStringBuilder.append("</table></body></html>");
return htmlStringBuilder.toString();
}
返回的html字符串:
<html><head><title>Excel to HTML using Java and POI library</title><style>table, th, td { border: 1px solid black; }</style></head><body><table><tr><td>序号</td><td>姓名</td><td>性别</td><td>联系方式</td><td>地址</td></tr><tr><td>1</td><td>张晓玲</td><td>女</td><td>11111111111</td><td>上海市浦东新区xx路xx弄xx号</td></tr><tr><td>2</td><td>王小二</td><td>男</td><td>1222222</td><td>上海市浦东新区xx路xx弄xx号</td></tr><tr><td>1</td><td>张晓玲</td><td>女</td><td>11111111111</td><td>上海市浦东新区xx路xx弄xx号</td></tr><tr><td>2</td><td>王小二</td><td>男</td><td>1222222</td><td>上海市浦东新区xx路xx弄xx号</td></tr><tr><td>1</td><td>张晓玲</td><td>女</td><td>11111111111</td><td>上海市浦东新区xx路xx弄xx号</td></tr><tr><td>2</td><td>王小二</td><td>男</td><td>1222222</td><td>上海市浦东新区xx路xx弄xx号</td></tr><tr><td>1</td><td>张晓玲</td><td>女</td><td>11111111111</td><td>上海市浦东新区xx路xx弄xx号</td></tr><tr><td>2</td><td>王小二</td><td>男</td><td>1222222</td><td>上海市浦东新区xx路xx弄xx号</td></tr><tr><td>1</td><td>张晓玲</td><td>女</td><td>11111111111</td><td>上海市浦东新区xx路xx弄xx号</td></tr><tr><td>2</td><td>王小二</td><td>男</td><td>1222222</td><td>上海市浦东新区xx路xx弄xx号</td></tr><tr><td>1</td><td>张晓玲</td><td>女</td><td>11111111111</td><td>上海市浦东新区xx路xx弄xx号</td></tr><tr><td>2</td><td>王小二</td><td>男</td><td>1222222</td><td>上海市浦东新区xx路xx弄xx号</td></tr><tr><td>1</td><td>张晓玲</td><td>女</td><td>11111111111</td><td>上海市浦东新区xx路xx弄xx号</td></tr><tr><td>2</td><td>王小二</td><td>男</td><td>1222222</td><td>上海市浦东新区xx路xx弄xx号</td></tr></table></body></html>
public String excelToHtmlStr(String excelPath) throws Exception {
FileInputStream fileInputStream=new FileInputStream(excelPath);
try (Workbook workbook=WorkbookFactory.create(new File(excelPath))){
DataFormatter dataFormatter=new DataFormatter();
FormulaEvaluator formulaEvaluator=workbook.getCreationHelper().createFormulaEvaluator();
org.apache.poi.ss.usermodel.Sheet sheet=workbook.getSheetAt(0);
StringBuilder htmlStringBuilder=new StringBuilder();
htmlStringBuilder.append("<html><head><title>Excel to HTML using Java and POI library</title>");
htmlStringBuilder.append("<style>table, th, td { border: 1px solid black; }</style>");
htmlStringBuilder.append("</head><body><table>");
for (Row row : sheet) {
htmlStringBuilder.append("<tr>");
for (Cell cell : row) {
CellType cellType=cell.getCellType();
if (cellType==CellType.FORMULA) {
formulaEvaluator.evaluateFormulaCell(cell);
cellType=cell.getCachedFormulaResultType();
}
String cellValue=dataFormatter.formatCellValue(cell, formulaEvaluator);
htmlStringBuilder.append("<td>").append(cellValue).append("</td>");
}
htmlStringBuilder.append("</tr>");
}
htmlStringBuilder.append("</table></body></html>");
return htmlStringBuilder.toString();
}
}
public String excelToHtmlStr(String excelPath) throws Exception {
try(ByteArrayOutputStream outputStream=new ByteArrayOutputStream()) {
Workbook workbook=new Workbook();
workbook.loadFromFile(excelPath);
workbook.saveToStream(outputStream, com.spire.xls.FileFormat.HTML);
return outputStream.toString();
}
}
有时我们是需要的不仅仅返回html字符串,而是需要生成一个html文件这时应该怎么做呢?一个改动量小的做法就是使用org.apache.commons.io包下的FileUtils工具类写入目标地址:
首先需要引入pom:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
相关代码:
String htmlStr=FileConvertUtil.pdfToHtmlStr("D:\\书籍\\电子书\\小说\\历史小说\\最后的可汗.doc");
FileUtils.write(new File("D:\\test\\doc.html"), htmlStr, "utf-8");
除此之外,还可以对上面的代码进行一些调整,已实现生成html文件,代码调整如下:
word原文件效果:
public static void wordToHtml(String wordPath, String htmlPath) {
try {
File sourceFile=new File(wordPath);
String path=htmlPath + File.separator + sourceFile.getName().substring(0, sourceFile.getName().lastIndexOf(".")) + ".html";
File file=new File(path); // 新建一个空白pdf文档
FileOutputStream os=new FileOutputStream(file);
Document doc=new Document(wordPath); // Address是将要被转化的word文档
HtmlSaveOptions options=new HtmlSaveOptions();
options.setExportImagesAsBase64(true);
options.setExportRelativeFontSize(true);
doc.save(os, options);
} catch (Exception e) {
e.printStackTrace();
}
}
转换成html的效果:
public void wordToHtml(String wordPath, String htmlPath) throws TransformerException, IOException, ParserConfigurationException {
htmlPath=FileUtil.getNewFileFullPath(wordPath, htmlPath, "html");
String ext=wordPath.substring(wordPath.lastIndexOf("."));
if (ext.equals(".docx")) {
word2007ToHtml(wordPath, htmlPath);
} else if (ext.equals(".doc")){
word2003ToHtml(wordPath, htmlPath);
} else {
throw new RuntimeException("文件格式不正确");
}
}
public void word2007ToHtml(String wordPath, String htmlPath) throws TransformerException, IOException, ParserConfigurationException {
//try(OutputStream out=Files.newOutputStream(Paths.get(path))){
try(FileOutputStream out=new FileOutputStream(htmlPath)){
word2007ToHtmlOutputStream(wordPath, out);
}
}
private void word2007ToHtmlOutputStream(String wordPath,OutputStream out) throws IOException {
ZipSecureFile.setMinInflateRatio(-1.0d);
InputStream in=Files.newInputStream(Paths.get(wordPath));
XWPFDocument document=new XWPFDocument(in);
XHTMLOptions options=XHTMLOptions.create().setIgnoreStylesIfUnused(false).setImageManager(new Base64EmbedImgManager());
// 使用内存输出流
XHTMLConverter.getInstance().convert(document, out, options);
}
public void word2003ToHtml(String wordPath, String htmlPath) throws TransformerException, IOException, ParserConfigurationException {
org.w3c.dom.Document htmlDocument=word2003ToHtmlDocument(wordPath);
// 生成html文件地址
try(OutputStream outStream=Files.newOutputStream(Paths.get(htmlPath))){
DOMSource domSource=new DOMSource(htmlDocument);
StreamResult streamResult=new StreamResult(outStream);
TransformerFactory factory=TransformerFactory.newInstance();
Transformer serializer=factory.newTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty(OutputKeys.METHOD, "html");
serializer.transform(domSource, streamResult);
}
}
private org.w3c.dom.Document word2003ToHtmlDocument(String wordPath) throws IOException, ParserConfigurationException {
InputStream input=Files.newInputStream(Paths.get(wordPath));
HWPFDocument wordDocument=new HWPFDocument(input);
WordToHtmlConverter wordToHtmlConverter=new WordToHtmlConverter(
DocumentBuilderFactory.newInstance().newDocumentBuilder()
.newDocument());
wordToHtmlConverter.setPicturesManager((content, pictureType, suggestedName, widthInches, heightInches) -> {
System.out.println(pictureType);
if (PictureType.UNKNOWN.equals(pictureType)) {
return null;
}
BufferedImage bufferedImage=ImgUtil.toImage(content);
String base64Img=ImgUtil.toBase64(bufferedImage, pictureType.getExtension());
// 带图片的word,则将图片转为base64编码,保存在一个页面中
StringBuilder sb=(new StringBuilder(base64Img.length() + "data:;base64,".length()).append("data:;base64,").append(base64Img));
return sb.toString();
});
// 解析word文档
wordToHtmlConverter.processDocument(wordDocument);
return wordToHtmlConverter.getDocument();
}
转换成html的效果:
public void wordToHtml(String wordPath, String htmlPath) {
htmlPath=FileUtil.getNewFileFullPath(wordPath, htmlPath, "html");
Document document=new Document();
document.loadFromFile(wordPath);
document.saveToFile(htmlPath, FileFormat.Html);
}
转换成html的效果:
因为使用的是免费版,存在页数和字数限制,需要完整功能的的可以选择付费版本。PS:这回76页的文档居然转成功了前50页。
图片版pdf原文件效果:
文字版pdf原文件效果:
public static void pdfToHtml(String pdfPath, String htmlPath) throws IOException, ParserConfigurationException {
File file=new File(pdfPath);
String path=htmlPath + File.separator + file.getName().substring(0, file.getName().lastIndexOf(".")) + ".html";
PDDocument document=PDDocument.load(new File(pdfPath));
Writer writer=new PrintWriter(path, "UTF-8");
new PDFDomTree().writeText(document, writer);
writer.close();
document.close();
}
图片版PDF文件验证结果:
文字版PDF文件验证结果:
public void pdfToHtml(String pdfPath, String htmlPath) throws IOException, ParserConfigurationException {
String path=FileUtil.getNewFileFullPath(pdfPath, htmlPath, "html");
PDDocument document=PDDocument.load(new File(pdfPath));
Writer writer=new PrintWriter(path, "UTF-8");
new PDFDomTree().writeText(document, writer);
writer.close();
document.close();
}
图片版PDF文件验证结果:
文字版PDF原文件效果:
public void pdfToHtml(String pdfPath, String htmlPath) throws IOException, ParserConfigurationException {
htmlPath=FileUtil.getNewFileFullPath(pdfPath, htmlPath, "html");
PdfDocument pdf=new PdfDocument();
pdf.loadFromFile(pdfPath);
pdf.saveToFile(htmlPath, com.spire.pdf.FileFormat.HTML);
}
图片版PDF文件验证结果:
因为使用的是免费版,所以只有前三页是正常的。。。有超过三页需求的可以选择付费版本。
文字版PDF原文件效果:
报错了无法转换。。。
java.lang.NullPointerException
at com.spire.pdf.PdfPageWidget.spr┢?(Unknown Source)
at com.spire.pdf.PdfPageWidget.getSize(Unknown Source)
at com.spire.pdf.PdfPageBase.spr???—(Unknown Source)
at com.spire.pdf.PdfPageBase.getActualSize(Unknown Source)
at com.spire.pdf.PdfPageBase.getSection(Unknown Source)
at com.spire.pdf.general.PdfDestination.spr︻┎?—(Unknown Source)
at com.spire.pdf.general.PdfDestination.spr┻┑?—(Unknown Source)
at com.spire.pdf.general.PdfDestination.getElement(Unknown Source)
at com.spire.pdf.primitives.PdfDictionary.setProperty(Unknown Source)
at com.spire.pdf.bookmarks.PdfBookmark.setDestination(Unknown Source)
at com.spire.pdf.bookmarks.PdfBookmarkWidget.spr┭┘?—(Unknown Source)
at com.spire.pdf.bookmarks.PdfBookmarkWidget.getDestination(Unknown Source)
at com.spire.pdf.PdfDocumentBase.spr??(Unknown Source)
at com.spire.pdf.widget.PdfPageCollection.spr┦?(Unknown Source)
at com.spire.pdf.widget.PdfPageCollection.removeAt(Unknown Source)
at com.spire.pdf.PdfDocumentBase.spr┞?(Unknown Source)
at com.spire.pdf.PdfDocument.loadFromFile(Unknown Source)
excel原文件效果:
public void excelToHtml(String excelPath, String htmlPath) throws Exception {
htmlPath=FileUtil.getNewFileFullPath(excelPath, htmlPath, "html");
Workbook workbook=new Workbook(excelPath);
com.aspose.cells.HtmlSaveOptions options=new com.aspose.cells.HtmlSaveOptions();
workbook.save(htmlPath, options);
}
转换成html的效果:
public void excelToHtml(String excelPath, String htmlPath) throws Exception {
String path=FileUtil.getNewFileFullPath(excelPath, htmlPath, "html");
try(FileOutputStream fileOutputStream=new FileOutputStream(path)){
String htmlStr=excelToHtmlStr(excelPath);
byte[] bytes=htmlStr.getBytes();
fileOutputStream.write(bytes);
}
}
public String excelToHtmlStr(String excelPath) throws Exception {
FileInputStream fileInputStream=new FileInputStream(excelPath);
try (Workbook workbook=WorkbookFactory.create(new File(excelPath))){
DataFormatter dataFormatter=new DataFormatter();
FormulaEvaluator formulaEvaluator=workbook.getCreationHelper().createFormulaEvaluator();
org.apache.poi.ss.usermodel.Sheet sheet=workbook.getSheetAt(0);
StringBuilder htmlStringBuilder=new StringBuilder();
htmlStringBuilder.append("<html><head><title>Excel to HTML using Java and POI library</title>");
htmlStringBuilder.append("<style>table, th, td { border: 1px solid black; }</style>");
htmlStringBuilder.append("</head><body><table>");
for (Row row : sheet) {
htmlStringBuilder.append("<tr>");
for (Cell cell : row) {
CellType cellType=cell.getCellType();
if (cellType==CellType.FORMULA) {
formulaEvaluator.evaluateFormulaCell(cell);
cellType=cell.getCachedFormulaResultType();
}
String cellValue=dataFormatter.formatCellValue(cell, formulaEvaluator);
htmlStringBuilder.append("<td>").append(cellValue).append("</td>");
}
htmlStringBuilder.append("</tr>");
}
htmlStringBuilder.append("</table></body></html>");
return htmlStringBuilder.toString();
}
}
转换成html的效果:
public void excelToHtml(String excelPath, String htmlPath) throws Exception {
htmlPath=FileUtil.getNewFileFullPath(excelPath, htmlPath, "html");
Workbook workbook=new Workbook();
workbook.loadFromFile(excelPath);
workbook.saveToFile(htmlPath, com.spire.xls.FileFormat.HTML);
}
转换成html的效果:
从上述的效果展示我们可以发现其实转成html效果不是太理想,很多细节样式没有还原,这其实是因为这类转换往往都是追求目标是通过使用文档中的语义信息并忽略其他细节来生成简单干净的 HTML,所以在转换过程中复杂样式被忽略,比如居中、首行缩进、字体,文本大小,颜色。举个例子在转换是 会将应用标题 1 样式的任何段落转换为 h1 元素,而不是尝试完全复制标题的样式。所以转成html的显示效果往往和原文档不太一样。这意味着对于较复杂的文档而言,这种转换不太可能是完美的。但如果都是只使用简单样式文档或者对文档样式不太关心的这种方式也不妨一试。
PS:如果想要展示效果好的话,其实可以将上篇文章《文档在线预览(一)通过将txt、word、pdf转成图片实现在线预览功能》说的内容和本文结合起来使用,即将文档里的内容都生成成图片(很可能是多张图片),然后将生成的图片全都放到一个html页面里 ,用html+css来保持样式并实现多张图片展示,再将html返回。开源组件kkfilevie就是用的就是这种做法。
kkfileview展示效果如下:
下图是kkfileview返回的html代码,从html代码我们可以看到kkfileview其实是将文件(txt文件除外)每页的内容都转成了图片,然后将这些图片都嵌入到一个html里,再返回给用户一个html页面。
*请认真填写需求信息,我们会在24小时内与您取得联系。