我对此进行了深入研究,尝试通过多种方式设置文件“大字体”版本的 id:
-
通过copy():var copiedFile = Drive.Files.copy(lpFile, spFile.id, options);
这会产生错误:
复制请求目前不支持生成的 ID
-
通过insert():var newFile = Drive.Files.insert(lpFile, doc.getBlob(), options);
这会产生错误:
Google 文档格式不支持生成的 ID
通过update():Drive.Files.update(lpFile, lpFile.id, doc.getBlob(), options);
此方法成功地从小打印文件更新“大打印”文件。但是,此特定行使用Document#getBlob() 方法,该方法在Document 的格式和丰富内容方面存在问题。特别是,正如您所提到的,不保留图像和表格(除其他外,如字体更改等)。比较pre 和post
似乎 - 如果可以找到从文档中导出格式化字节内容的适当方法 - update() 方法最有希望。请注意,Apps Script 客户端库中的update() 方法需要Blob 输入(即doc.getBlob().getBytes() 将不起作用),因此基本限制可能是生成的@987654344 中(缺乏)对丰富格式信息的支持@ 数据。考虑到这一点,我尝试了几种方法从“小字体”文件中获取“格式化”Blob 数据:
- 通过
Document#getAs(mimetype):Drive.Files.export(lpFile, lpFile.id, doc.getAs(<type>), options);
对于看似合理的类型,它会失败并出现错误:
MimeType.GOOGLE_DOCS:很抱歉,出现服务器错误。请稍等,然后重试。
MimeType.MICROSOFT_WORD:不支持从application/vnd.google-apps.document 转换为application/vnd.openxmlformats-officedocument.wordprocessingml.document。
这些错误确实有道理,因为内部 Google Docs MimeType 不可导出(您不能“下载为”此文件类型,因为数据已保留但 Google 希望保留它),Document#getAs(mimeType) 的文档表明文档服务仅支持 PDF 导出。实际上,尝试用 doc.getBlob() 强制 Blob 与 getAs(mimeType) 失败,并出现错误:
不支持从application/pdf 转换为application/vnd.openxmlformats-officedocument.wordprocessingml.document。
使用DriveApp 获取Blob,而不是文档服务:
Drive.Files.update(lpFile, lpFile.id, DriveApp.getFileById(smallPrintId).getBlob(), options);
这与doc.getBlob() 存在相同的问题,并且可能使用相同的内部方法。
使用DriveApp#getAs会出现与Document#getAs相同的错误
考虑到原生 Apps Script 实现的限制,我随后使用高级服务获取了Blob 数据。这有点棘手,因为返回的File 资源实际上不是文件,而是有关文件的元数据。使用 REST API 获取 Blob 需要将文件导出到所需的 MimeType。从上面我们知道,PDF 格式的Blob 无法正确导入,因为这是上述尝试使用的格式。我们也知道 Google Docs 格式不可导出,所以只剩下 MS Word 的.docx。
var blob = getBlobViaURL_(smallPrintId, MimeType.MICROSOFT_WORD);
Drive.Files.update(lpFile, lpFile.id, blob, options);
其中getBlobViaURL_ 为 (still-broken) Drive.Files.export() Apps 脚本方法实现了来自 this SO question 的解决方法。
此方法成功地使用“小字体”文件中的确切内容更新现有的“大字体”文件 - 至少对于我的测试文档而言。鉴于它涉及下载内容,而不是使用导出方法可用的内部现有数据,因此对于较大的文件可能会失败。
测试脚本:
function copyContentFromAtoB() {
var smallPrintId = "some id";
var largePrintId = "some other id";
// You must first enable the Drive "Advanced Service" before this will work.
// Get the file metadata of the to-be-updated file.
var lpFile = Drive.Files.get(largePrintId);
// View available options on the relevant Drive REST API pages.
var options = {
updateViewedDate: false,
};
// Ideally this would use Drive.Files.export, but there is a bug in the Apps Script
// client library's implementation: https://issuetracker.google.com/issues/36765129
var blob = getBlobViaURL_(smallPrintId, MimeType.MICROSOFT_WORD);
// Replace the contents of the large print version with that of the small print version.
Drive.Files.update(lpFile, lpFile.id, blob, options);
}
// Below function derived from https://stackoverflow.com/a/42925916/9337071
function getBlobViaURL_(id, mimeType) {
var url = "https://www.googleapis.com/drive/v2/files/"+id+"/export?mimeType="+ mimeType;
var resp = UrlFetchApp.fetch(url, {
headers: { Authorization: 'Bearer ' + ScriptApp.getOAuthToken()}
});
return resp.getBlob();
}