我正在使用外部 API 来创建和下载数据提取。创建数据提取后,API 响应将包含一个 url。此网址是直接下载链接 - 单击它会打开一个新的浏览器选项卡,该选项卡会自动将文件下载到我的下载文件夹中。我正在尝试自动化此过程,这样我就不必手动下载和重命名文件。一切正常,除了文件总是以默认名称下载。我们会说这是“123456123456.csv.gz”以保持模糊性。
我关注的链接格式如下-
https://storage.googleapis.com/(custom storage name)/(data extract id)/123456123456.csv.gz?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=(google service account credentials)&X-Goog-Date=(date)&X-Goog-Expires=(time until expiration)&X-Goog-SignedHeaders=host&X-Goog-Signature=(long string of number and letters)
我目前正在使用 puppeteer 打开一个指向该 url 的新浏览器选项卡,该选项卡会下载文件,然后关闭 puppeteer-
async function downloadFile (url) {
try {
const browser = await puppeteer.launch(
{headless: false}
);
const page = await browser.newPage();
await page.goto(`${url}`);
await page.waitForTimeout(3000); // just in case it takes a second
await browser.close();
}
catch (error) {
console.error(error);
}
}
我尝试直接编辑具有自定义文件名的链接,如下所示-
...
const autoFileName = '000000000000.csv.gz';
const customFileName = `${date}-${reportingLevel}.csv.gz`;
for (let i = 0; i < urls.length; i++) {
const newUrl = url.replace(autoFileName, customFileName);
downloadFile(newUrl);
...
但是当我在浏览器中打开新网址时,它没有下载文件,而是给我一个像这样的页面 -
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>Access denied.</Message>
<Details>The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.</Details>
<StringToSign>(sensitive information)</StringToSign>
<CanonicalRequest>GET (sensitive information) UNSIGNED-PAYLOAD</CanonicalRequest>
</Error>
我在谷歌上找不到任何关于这些链接的文档 - 如果有人能找到任何文档,我会喜欢它!
起初我以为网址的“123456123456.csv.gz”部分只是下载文件的名称,但现在我意识到该文件很可能以“123456123456.csv.gz”的形式存储在他们的谷歌存储中'.
有人知道如何自动重命名我的文件,这样我就不必手动操作吗?我确实尝试使用 axios/fs 来下载,但甚至没有下载该文件,更不用说重命名它了。我以前很少使用 axios,所以可能我做错了。
提前致谢!
使用 Puppeteer 似乎有点大材小用,你真的需要涉及浏览器吗?为什么不使用 axios,正如您在问题标签中提到的那样?这是一个基本的工作示例:
const axios = require('axios');
const fs = require('fs');
const urls = ['https://placehold.co/400', 'https://placehold.co/600'];
(async () => {
for (const url of urls) {
const { data } = await axios.get(url, { responseType: 'stream' });
const originalFilename = url.split('/').pop();
const dest = `foo-${originalFilename}.svg`;
await data.pipe(fs.createWriteStream(dest));
}
})();