Загрузите большой двоичный объект изображения из Google Фото, используя JavaScript и REST API - PullRequest
2 голосов
/ 06 августа 2020

Я не могу загрузить большой двоичный объект изображения в свой JavaScript клиент с помощью REST API Google Фото. Мой XMLHttpRequest получает 404. У меня есть действующий токен OAuth, и я могу перечислить mediaItems. Токен был сгенерирован с использованием автономного кода доступа. Один и тот же метод загрузки XMLHttpRequest работает как с GDrive, так и с Dropbox, что позволяет мне отображать ход загрузки.

Я пробовал использовать суффиксы baseUrl «= d» и «= w123h345- c» (где 123 и 345 - ширина и высота изображения соответственно). Я пробовал использовать как fetch, так и XMLHttpRequest с различными комбинациями доступа с учетными данными (например, используя access_token в качестве параметра URL-адреса или в заголовке авторизации.

Обратите внимание, что тот же URL-адрес отлично работает в строке URL-адреса Chrome, либо загружая файл, либо показываю версию с полным разрешением. Я также могу загрузить файл из командной строки, используя curl с URL-адресом, передающим access_token в качестве параметра. Если я отправлю команду curl с помощью настройки OPTIONS, я НЕ получаю доступ -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"
< 

Я нашел аналогичный вопрос SO без ответов.

Все мое тестирование проводилось на localhost: 3000, так как у меня еще нет проверки OAuth для области photoslibrary.readonly. Во время тестирования, как и ожидалось, я получаю всплывающее окно аутентификации «Advanced» и 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)
})

1 Ответ

0 голосов
/ 07 августа 2020

Похоже, что конечные точки Google Фото не поддерживают доступ CORS к пиксельным данным.

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

Опять же, можно использовать curl или imageтеги для отображения пикселей. Вы просто не можете получить данные в клиенте JS, пока не будет добавлен доступ CORS.

...