使用Google Apps脚本将文件从URL上传到Google Drive



我正试图通过Google Apps脚本将文件上传到我的Google Drive实例。

我有文件的URL,但由于本地服务器的性质(在本地运行(,我只能在本地下载。这意味着我只能在本地管理文件,只有响应才能发送到我的谷歌应用程序脚本。

我得到的响应(来自可用文件列表(如下:

{
"contextid": 40,
"component": "mod_folder",
"filearea": "content",
"itemid": 0,
"filepath": "/",
"filename": "mypdf.pdf",
"isdir": false,
"url": "http://localhost/server/pluginfile.php/40/mod_folder/content/0/mypdf.pdf",
"timemodified": 1645463016,
"timecreated": 1645462995,
"filesize": 1504856,
"author": "Admin",
"license": "unknown"
}

并使用上面的url执行axios.get(((以及一些身份验证(,返回这个JSON对象:

{
"config": {transitional: {...}, transformRequest: Array(1),...},
"data": "%PDF-1.5rn%����rn1 0 objrn<</Type/Catalog/Pages 2 0 R/Lang(en-GB) /StructTreeRoot 70 0 R/MarkInfo<</Marked true>>>>rnendobjrn2 0.......",
"headers": "{accept-ranges: 'bytes', cache-control: 'private, must-revalidate, pre-check=0, post-check=0, max-age=0, no-transform',..."
"request": "XMLHttpRequest {onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …}",
"status": 200
"statusText": "OK"
}

数据的值似乎代表了mypdf.pdf的字符串化值,我的计划是将其作为字符串发送到我的Script,用它创建一个blob,并上传到我的驱动器。


我的JS客户端脚本如下所示:

axios.post('https://script.google.com/macros/s/AKfy....XEby/exec', { type: 'application/pdf', file: r.data })
/*A*/     .then(r => console.log(r))
.catch(e => console.error(e));

和我的谷歌应用程序脚本:

function doPost(e) {
const folderId = "root";
const blob = Utilities.newBlob(JSON.parse(e.postData.contents.file), 'application/pdf', 'mypdf.pdf');
const file = DriveApp.getFolderById(folderId).createFile(blob);
const responseObj = {filename: file.getName(), fileId: file.getId(), fileUrl: file.getUrl()};
return ContentService.createTextOutput(JSON.stringify(responseObj));
}

不幸的是,我的脚本中的/A/一直返回相同的消息,即

{
"config": {transitional: {...}, transformRequest: Array(1),...},
"data": "<!DOCTYPE html><html><head><link rel="shortcut icon" href="//ssl.gstatic.com/docs/script/images/favicon.ico"><title>Error</title><style ty",
"headers": "{alt-svc: 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-…3"; ma=2592000,quic=":443"; ma=2592000; v="46,43"',..."
"request": "XMLHttpRequest {onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …}",
"status": 200
"statusText": ""
}

这实际上是一个错误并且数据的值指示存在SyntaxError: Unexpected token u in JSON at position 0 (line 5, file "Code")。我的5号线怎么了?是我的JSON.parse((吗?


我知道上传mypdf.pdf文件的实际内容,然后将其包装在脚本中的blob中可能不是最好的主意。然而,我将无法发送url,因为它将无法远程工作。我真的很困惑,不知道该怎么解决这个问题。为什么我收到这个消息?在将响应(实际的pdf内容(发布到我的脚本之前,我需要将其包装在一个blob中吗?

很遗憾,我无法从您的问题中看到您的整个脚本。因此,我理解了你的问题,所以这只是我的猜测。

修改要点:

  • 来自doing axios.get() with the url from above (and some authentication), returns this JSON object:、的以下样本数据

    {
    "config": {transitional: {...}, transformRequest: Array(1),...},
    "data": "%PDF-1.5rn%����rn1 0 objrn<</Type/Catalog/Pages 2 0 R/Lang(en-GB) /StructTreeRoot 70 0 R/MarkInfo<</Marked true>>>>rnendobjrn2 0.......",
    "headers": "{accept-ranges: 'bytes', cache-control: 'private, must-revalidate, pre-check=0, post-check=0, max-age=0, no-transform',..."
    "request": "XMLHttpRequest {onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …}",
    "status": 200
    "statusText": "OK"
    }
    
  • 我认为在您的脚本中,您可能使用了没有选项的axios.get。当使用axios.get作为默认值时,二进制数据将作为字符串检索。我想这可能就是你问题的原因。

  • 在这种情况下,请使用{responseType: 'arraybuffer'}选项。通过这种方式,可以获得二进制数据作为缓冲器。使用此方法,数据将作为int8array数据发送到您的Web应用程序。这样,数据就可以与Utilities.newBlob一起使用。

  • 当我看到你的谷歌应用程序脚本时,只有fileconst blob = Utilities.newBlob(JSON.parse(e.postData.contents.file), 'application/pdf', 'mypdf.pdf')一起使用。

  • 并且还要求JSON.parse(e.postData.contents.file)JSON.parse(e.postData.contents).file。请小心。

删除此问题后,修改后的脚本如下。

Axios侧:

为了检索doing axios.get() with the url from above (and some authentication), returns this JSON object:的数据,请将URL设置为contentUrl。此外,请将您的Web应用程序URL设置为webAppsUrl

const contentUrl = "###"; // Please set the URL of conente you want to download.
const webAppsUrl = "https://script.google.com/macros/s/###/exec"; // Please set your Web Apps URL.
axios.get(contentUrl, {responseType: "arraybuffer"})
.then(res => {
axios.post(webAppsUrl, JSON.stringify([...new Int8Array(res.data)]))
.then((res) => console.log(res.data))
.catch((err) => console.log(err));
})
.catch(err => console.log(err));
  • 我不能理解你的整个剧本。所以请使用我提出的脚本进行修改。

  • 不幸的是,在当前阶段,Web应用程序无法使用二进制数据。因此,检索到的二进制数据是通过转换为字符串值来发送的。但是,在这种情况下,为了解码数据,二进制数据被转换为int8array数据。

谷歌应用程序脚本端:

function doPost(e) {
const folderId = "root";
const blob = Utilities.newBlob(JSON.parse(e.postData.contents), 'application/pdf', 'mypdf.pdf'); // Modified
const file = DriveApp.getFolderById(folderId).createFile(blob);
const responseObj = { filename: file.getName(), fileId: file.getId(), fileUrl: file.getUrl() };
return ContentService.createTextOutput(JSON.stringify(responseObj));
}

注:

  • 虽然在您的问题中,Web应用程序的设置不包括在内,但从您的脚本中,我猜Web应用程序设置是Execute as: MeWho has access to the app: Anyone(使用新的IDE(。请小心
  • 当我使用contentUrl的示例URL测试我提出的脚本时,我可以确认PDF数据可以发送到Web应用程序并将其创建为文件。但是,当您测试它并出现错误时,请再次确认您的Web应用程序和脚本设置
  • 当您修改Google Apps脚本时,请将部署修改为新版本。这样,修改后的脚本就会反映在Web应用程序中。请小心
  • 你可以在";在不改变用于新IDE的Web应用程序的URL的情况下重新部署Web应用程序">

参考文献:

  • Web应用程序
  • 使用Google应用程序脚本利用Web应用程序
  • axios

最新更新