使用JavaScript和REST API从Google相册下载图像Blob [英] Download image blob from Google Photos using JavaScript and REST API

查看:89
本文介绍了使用JavaScript和REST API从Google相册下载图像Blob的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法使用Google Photos REST API在JavaScript客户端中下载图片Blob.我的XMLHttpRequest收到404.我有一个有效的OAuth令牌,可以列出mediaItems.令牌是使用离线访问代码生成的. GDrive和Dropbox都可以使用相同的XMLHttpRequest下载方法,这样我就可以显示下载进度.

I cannot download an image blob in my JavaScript client using the Google Photos REST API. My XMLHttpRequest is getting a 404. I have a valid OAuth token and can list the mediaItems. The token was generated using an offline access code. The same XMLHttpRequest download method works with both GDrive and Dropbox, allowing me to show download progress.

我尝试使用"= d"和"= w123h345-c" baseUrl后缀(其中123和345是图像的相应宽度和高度).我尝试将fetch和XMLHttpRequest与凭据访问的各种组合结合使用(例如,将access_token用作URL参数或在Authorization标头中使用.

I've tried using the "=d" and "=w123h345-c" baseUrl suffixes (where 123 and 345 are the respective width and height of the image). I've tried using both fetch and XMLHttpRequest with various combinations of credentialed access (e.g. using access_token as a URL param or in the Authorization header.

请注意,相同的URL在Chrome URL栏中可以正常工作,无论是下载文件还是显示完整版本.我还可以使用curl通过从命令行下载文件,并将URL传递给access_token作为参数.如果我使用OPTIONS设置发送curl命令,则响应中不会显示Access-Control-Allow-Origin:

Note that the same URL works fine in the Chrome URL bar, either downloading the file or showing the full-res version. I can also download the file from the command line using curl with the URL passing the access_token as a parameter. If I send the curl command using the OPTIONS setup, I do NOT get Access-Control-Allow-Origin in the response:

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"
< 

我发现了一个类似SO问题,但没有答案

I've found a similar SO question with no answers.

我所有的测试都在localhost:3000上进行,因为我尚未对photoslibrary.readonly范围进行OAuth验证.我得到了高级"如预期的那样,在测试过程中会弹出auth弹出窗口,并且access_token有效,可用于列出和获取mediaItems,但不适用于媒体下载.

All of my testing has been on localhost:3000 since I do not yet have OAuth validation for the photoslibrary.readonly scope. I get the "Advanced" auth popup during testing, as expected, and the access_token is valid and can be used to list and get mediaItems, just not with the media downloads.

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相册端点似乎不支持对像素数据的CORS访问.

It looks like the Google Photos endpoints do not support CORS access to pixel data.

https://issuetracker.google.com/issues/118662029

同样,可以使用curl或< img>标签以显示像素.在添加CORS访问之前,您只是无法在客户端JS中获取数据.

Again, it is fine to use curl or <img> tags to display the pixels. You just cannot get the data in the client JS until CORS access is added.

这篇关于使用JavaScript和REST API从Google相册下载图像Blob的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆