javascript - 无法使用 Blob 对象在客户端打开“docx”文件 - vanilla JavaScript
问题描述
这是客户端的代码,它是一个最小的、完整的和可验证的代码段,允许其他开发人员自己测试。
// requires: a string that contains html tags
// returns: a word document that can be downloaded with extension .doc or docx
// @ param cvAsHTML is a string that contains html tags
const preHtml = "<html xmlns:v='urn:schemas-microsoft-com:vml' xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/html4/loose.dtd\'><head><meta charset='utf-8'></head><body>";
const postHtml = "</body></html>";
const html = preHtml + cvAsHTML + postHtml;
let filename = "filename";
const blob = new Blob(["\ufeff", html], { type: "application/msword"});
上面的代码片段就像一个魅力。请注意,XML 模式是多余的,实际上是不必要的。doc 文件可以在没有它们的情况下工作,但必须存在 head 和 body 标签。
对于docx
文件,我无法下载文件。该文件似乎已损坏,经过几次试验,我真的不知道该怎么办。这是 docx 文件的代码:
const preHtml = "<?xml version='1.0' encoding='UTF-8?><html xmlns:v='urn:schemas-microsoft-com:vml' xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/html4/loose.dtd\'><head><meta charset='utf-8'></head><body>";
const postHtml = "</body></html>";
const html = preHtml + cvAsHTML + postHtml;
let filename = "filename.docx";
const blob = new Blob(["\ufeff", html], { type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main"});
注意:我已经更改了 Blob 对象中的 MIME 类型,并尝试了不同的其他选项,例如等application/zip
,application/octet-stream
但均无济于事。我还更改了prehtml
变量以包括:
<?xml version='1.0' encoding='UTF-8?>
鉴于我了解 docx 文件本质上是包含 xml 段的压缩文件...
非常感谢您提供的任何帮助。
编辑:2019 年 12 月 16 日
这是我在@dw_建议的实现后截取的截图:
using 的实现JSZip
无法按预期工作,因为:
- 浏览器本身不允许用户在 microsoft word 中打开文件,就像打开文件一样
doc
; - 用户必须先保存文件,但即使那样,文件也不会打开,因为它已损坏。
解决方案
.docx
是压缩文件的集合,使用简化的最小 DOCX 文档作为指导,我创建了一个".zip"
包含主word/document.xml
文件和 3 个附加必需文件的文件。
有关.docx
文件的更多信息,请参见:DOCX 的非正式介绍
// Other needed files
const REQUIRED_FILES = {
content_types_xml: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
<Default Extension="xml" ContentType="application/xml"/>
<Override PartName="/word/document.xml"
ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
</Types>`,
rels: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
Target="word/document.xml"/>
</Relationships>`,
document_xml_rels: `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
</Relationships>`
};
/// --
const preHtml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"
xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"
xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk"
xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml"
xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 wp14">
<w:body><w:p w:rsidR="005F670F" w:rsidRDefault="005F79F5">`;
const postHtml = `<w:bookmarkStart w:id="0" w:name="_GoBack"/>
<w:bookmarkEnd w:id="0"/>
</w:p>
<w:sectPr w:rsidR="005F670F">
<w:pgSz w:w="12240" w:h="15840"/>
<w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="720" w:footer="720"
w:gutter="0"/>
<w:cols w:space="720"/>
<w:docGrid w:linePitch="360"/>
</w:sectPr>
</w:body>
</w:document>`;
const cvAsHTML = `<w:r><w:t>Sample content inside .docx</w:t></w:r>`;
const html = preHtml + cvAsHTML + postHtml;
function generateDocx(fname) {
let zip = new JSZip();
// prerequisites:
zip.file("_rels/.rels", REQUIRED_FILES.rels);
zip.file("[Content_Types].xml", REQUIRED_FILES.content_types_xml);
zip.file("word/_rels/document.xml.rels", REQUIRED_FILES.document_xml_rels);
//
zip.file("word/document.xml", html);
zip.generateAsync({type:"blob"}).then(function(content) {
saveAs(content, fname + ".docx");
});
}
<script src="https://cdn.jsdelivr.net/npm/file-saver@2.0.2/dist/FileSaver.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.2.2/jszip.min.js"></script>
<button onclick="generateDocx('test_1')">Download .docx</button>
使用的库
外部演示(因为内联可能不起作用)
推荐阅读
- html - 将文本字符串附加到现有元素 jQuery
- c++ - 表达式“void()”及其在三元条件下的有效性
- neo4j - Neo4j BatchInserter 计数失败,我该怎么办?
- gitlab-ci - 当某些文件存在时,如何使 gitlab-ci.yml 中的工作失败?
- ckeditor - 从 Word 文档粘贴时的 ckeditor 5 和字体大小
- flutter - 拖放 png 图像应该覆盖背景图像,并且能够在颤动中调整大小和旋转(照片编辑器应用程序)
- c++ - 为什么 if else 结构在 c++ 中不起作用?
- python - TypeError:PyCaret 回归中 -: 'str' 和 'int' 的不支持的操作数类型
- search - 如何在VS Code的文件夹中列出特定扩展名的所有文件?
- mysql - 为 int 列插入时,mySQL 如何舍入浮点数