GDrive API v3文件。获得下载进度吗?

问题描述 投票:0回答:1

如何显示使用gapi客户端v3 API从GDrive下载大文件的进度?

我正在使用v3 API,并且我尝试在标头中使用Range请求,该请求有效,但下载速度非常慢(如下所示)。我的最终目标是播放4K视频。 GDrive limits playback to 1920x1280。我的计划是通过v3 API将块下载到IndexedDB并从本地缓存的数据中播放。我通过Range请求使用下面的代码来完成这项工作,但它的速度太慢了。直接下载完整的438 MB测试文件(例如,通过GDrive网页)通常需要30-35秒钟,与此同时,每1 MB范围请求几乎需要30-35秒钟。感觉GDrive后端正在读取并发送每个子范围的完整文件吗?

我还尝试使用XHR并提取文件,但失败。我一直在使用webContent链接(通常以&export=download结尾),但是我无法正确获取访问标头。我收到CORS或其他奇怪的权限问题。在<image><video> src标记中,webContent链接可以正常工作。我希望这是由于特殊的权限处理或某些标头信息所致,我缺少浏览器专门为这些媒体标签处理的标头信息。我的解决方案必须能够读取私有(非公共,不可共享)链接,因此必须使用v3 API。

对于小于GDrive限制的视频文件,我可以设置MediaRecorder并使用<video>元素获取进度数据。不幸的是,1920x1080的限制使大型文件无法使用这种方法,在这种情况下,进度反馈就显得尤为重要。

这是客户端的gapi Range代码,它可以工作,但是对于大文件(400 MB-2 GB)来说速度太慢了:

const getRange = (start, end, size, fileId, onProgress) => (
  new Promise((resolve, reject) => gapi.client.drive.files.get(
    { fileId, alt: 'media', Range: `bytes=${start}-${end}` },
    // { responseType: 'stream' }, Perhaps this fails in the browser?
  ).then(res => {
    if (onProgress) {
      const cancel = onProgress({ loaded: end, size, fileId })
      if (cancel) {
        reject(new Error(`Progress canceled download at range ${start} to ${end} in ${fileId}`))
      }
    }
    return resolve(res.body)
  }, err => reject(err)))
)

export const downloadFileId = async (fileId, size, onProgress) => {
  const batch = 1024 * 1024
  try {
    const chunks = []
    for (let start = 0; start < size; start += batch) {
      const end = Math.min(size, start + batch - 1)
      const data = await getRange(start, end, size, fileId, onProgress)
      if (!data) throw new Error(`Unable to get range ${start} to ${end} in ${fileId}`)
      chunks.push(data)
    }
    return chunks.join('')
  } catch (err) {
    return console.error(`Error downloading file: ${err.message}`)
  }
}

身份验证对我来说很好,我也可以使用其他GDrive命令。我目前正在使用drive.photos.readonly范围,但是即使使用完整的写权限范围,我也遇到相同的问题。

可能地,我在使用gapi运行客户端时无法获得流(在服务器端的节点上工作正常)。这太奇怪了。如果我可以得到一个流,我想我可以用它来取得进展。每当我为responseType: 'stream'添加注释行时,都会出现以下错误:The server encountered a temporary error and could not complete your request. Please try again in 30 seconds. That’s all we know.当然,等待无济于事,如果我不请求流,则可以得到成功的响应。

google-drive-api video-streaming html5-video gapi
1个回答
0
投票

我改用直接使用XMLHttpRequest,而不是使用gapi包装器。 Google provides these instructions for using CORS显示了如何将使用gapi的任何请求转换为XHR。然后,您可以附加到onprogress事件(以及onload,onerror和其他事件)以进行进步。

这是问题中的downloadFileId方法的插入式替换代码,带有大量调试脚手架:

const xhrDownloadFileId = (fileId, onProgress) => new Promise((resolve, reject) => {
  const user = gapi.auth2.getAuthInstance().currentUser.get()
  const oauthToken = user.getAuthResponse().access_token
  const xhr = new XMLHttpRequest()
  xhr.open('GET', `https://www.googleapis.com/drive/v3/files/${fileId}?alt=media`)
  xhr.setRequestHeader('Authorization', `Bearer ${oauthToken}`)
  xhr.responseType = 'blob'
  xhr.onloadstart = event => {
    console.log(`xhr ${fileId}: on load start`)
    const { loaded, total } = event
    onProgress({ loaded, size: total })
  }
  xhr.onprogress = event => {
    console.log(`xhr ${fileId}: loaded ${event.loaded} of ${event.total} ${event.lengthComputable ? '' : 'non-'}computable`)
    const { loaded, total } = event
    onProgress({ loaded, size: total })
  }
  xhr.onabort = event => {
    console.warn(`xhr ${fileId}: download aborted at ${event.loaded} of ${event.total}`)
    reject(new Error('Download aborted'))
  }
  xhr.onerror = event => {
    console.error(`xhr ${fileId}: download error at ${event.loaded} of ${event.total}`)
    reject(new Error('Error downloading file'))
  }
  xhr.onload = event => {
    console.log(`xhr ${fileId}: download of ${event.total} succeeded`)
    const { loaded, total } = event
    onProgress({ loaded, size: total })
    resolve(xhr.response)
  }
  xhr.onloadend = event => console.log(`xhr ${fileId}: download of ${event.total} completed`)
  xhr.ontimeout = event => {
    console.warn(`xhr ${fileId}: download timeout after ${event.loaded} of ${event.total}`)
    reject(new Error('Timout downloading file'))
  }
  xhr.send()
})
© www.soinside.com 2019 - 2024. All rights reserved.