我无法使用 Google Photos REST API 在 JavaScript 客户端中下载图像 blob。我的 XMLHttpRequest 收到 404。我有一个有效的 OAuth 令牌,可以列出媒体项目。该令牌是使用离线访问代码生成的。相同的 XMLHttpRequest 下载方法适用于 GDrive 和 Dropbox,允许我显示下载进度。
我尝试使用“=d”和“=w123h345-c”baseUrl 后缀(其中 123 和 345 分别是图像的宽度和高度)。我尝试过将 fetch 和 XMLHttpRequest 与凭据访问的各种组合一起使用(例如,使用 access_token 作为 URL 参数或在授权标头中使用。
请注意,相同的 URL 在 Chrome URL 栏中可以正常工作,无论是下载文件还是显示完整版本。我还可以使用curl 从命令行下载文件,并将URL 作为参数传递access_token。如果我使用选项设置发送curl命令,我不会在响应中得到Access-Control-Allow-Origin:
curl --verbose --output foo -H "Origin: http://localhost:3000" \
-H "Access-Control-Request-Method: GET" \
-H "Access-Control-Request-Headers: X-Requested-With" \
-X OPTIONS \
"https://lh3.googleusercontent.com/lr/<baseUrl>=d?access_token=<access_token>"
返回以下响应标头:
< HTTP/2 200
< access-control-expose-headers: Content-Length
< etag: "v3d"
< expires: Fri, 01 Jan 1990 00:00:00 GMT
< cache-control: private, max-age=86400, no-transform
< content-disposition: attachment;filename="MA-Distancing.png"
< content-type: image/png
< vary: Origin
< x-content-type-options: nosniff
< date: Thu, 06 Aug 2020 20:06:22 GMT
< server: fife
< content-length: 772787
< x-xss-protection: 0
< alt-svc: h3-29=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
<
我发现了一个类似的问题,但没有答案。
我的所有测试都在 localhost:3000 上进行,因为我还没有对 photoslibrary.readonly 范围进行 OAuth 验证。正如预期的那样,我在测试期间收到“高级”身份验证弹出窗口,并且 access_token 有效并且可用于列出和获取媒体项目,但不能用于媒体下载。
export const xhrDownloadURL = (url, accessToken, body, onProgress) => new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', url)
if (accessToken) xhr.setRequestHeader('Authorization', `Bearer ${accessToken}`)
xhr.setRequestHeader('Access-Control-Allow-Credentials', true)
xhr.responseType = 'blob'
const updateProgress = e => {
if (onProgress) {
const { loaded, total } = e
const cancel = onProgress({ loaded, size: total })
if (cancel.type === CACHE_CANCELED) {
reject(new Error(`onProgress canceled download at range ${loaded} of ${total} in ${url}`))
}
}
}
xhr.onloadstart = updateProgress
xhr.onprogress = updateProgress
xhr.onabort = event => {
console.warn(`xhr ${url}: download aborted at ${event.loaded} of ${event.total}`)
reject(new Error('Download aborted'))
}
xhr.onerror = event => {
console.error(`xhr ${url}: download error at ${event.loaded} of ${event.total}`)
reject(new Error('Error downloading file'))
}
xhr.onload = event => {
const { loaded, total } = event
if (onProgress) onProgress({ loaded, size: total })
const data = process.env.NODE_ENV === 'test' && Array.isArray(xhr.response) && xhr.response.length === 1 ? xhr.response[0] : xhr.response
resolve(data)
}
xhr.onloadend = (/* event */) => {
// console.log(`xhr ${url}: download of ${event.total} completed`)
}
xhr.ontimeout = event => {
console.warn(`xhr ${url}: download timeout after ${event.loaded} of ${event.total}`)
reject(new Error('Timout downloading file'))
}
xhr.send(body)
})
Google Photos 端点似乎不支持 CORS 访问像素数据。
https://issuetracker.google.com/issues/118662029
再次强调,可以使用curl 或 标签来显示像素。在添加 CORS 访问之前,您只是无法在客户端 JS 中获取数据。
=d
参数添加到图像基本 URL 的末尾,则 Google 支持照片下载。 如果您通过有效的
baseUrl
查询获取图像详细信息,您将找到 mediaItems
。
请查看本文档中的表格。 如果您将下载参数 (=d) 附加到 Google Photos 图片的基本 URL 的末尾,它应该能够满足您的要求。希望这有帮助!