2017-09-11 42 views
13

我正试图遵循this指南,通过Google API在Google云端硬盘上进行可恢复的上传。如何使用gapi和可恢复的上传将文件上传到Google驱动器?

这是我的代码,您可以看到它会根据指南要求提供2个请求,第一部分创建元数据,然后使用位置开始上传带有第一个请求创建的会话的文件。

 const file = new File(['Hello, world!'], 'hello world.txt', { type: 'text/plain;charset=utf-8' }); 
     const contentType = file.type || 'application/octet-stream'; 

     const reqMetadata = gapi.client.request({ 
      'path': 'upload/drive/v3/files', 
      'method': 'POST', 
      'params': { 'uploadType': 'resumable' }, 
      'headers': { 
       'X-Upload-Content-Type': file.type, 
       'X-Upload-Content-Length': file.size, 
       'Content-Type': 'application/json; charset=UTF-8' 
      }, 
      'body': { 
       'name': file.name, 
       'mimeType': contentType, 
       'Content-Type': contentType, 
       'Content-Length': file.size 
      } 
     }); 

     reqMetadata.execute((respMetadata, rawRespMetadata: any) => { 
      const locationUrl = JSON.parse(rawRespMetadata).gapiRequest.data.headers.location; 

      const reader = new FileReader(); 

      reader.onload = (e) => { 
       const reqFile = gapi.client.request({ 
        'path': locationUrl, 
        'method': 'PUT', 
        'headers': { 
         'Content-Type': file.type, 
         'Content-Length': file.size 
        }, 
        'body': reader.result 
       }); 

       reqFile.execute(respFile => { 
        console.log(respFile); 
       }); 
      }; 

      reader.readAsArrayBuffer(file); 
     }); 

什么问题?

嗯,看来谷歌API库不喜欢的文件/字节数组作为身体上的gapi.client.request和他们截断它拿走see image

什么是传递文件的正确方法是什么?我试过身体:文件和正文:reader.result但相同的结果

PS:gapi已经完全验证&用auth2初始化,我可以创建文件/目录。

编辑1:

GAPI库只是jsoing的FileArray,因此JSON功能,将它修改为一个空的对象,没办法让它工作..必须有所缺失。

编辑2:

我做到了没有GAPI工作,它正确地上传文件,但我有一些问题与CORS

  reader.onload = (e) => {      

       const authHeader = `Bearer ${this.auth.currentUser.get().getAuthResponse().access_token}`; 
       const headers = new Headers({ 
        'Authorization': authHeader, 
        'Content-Type': file.type 
       }); 
       const options = new RequestOptions({ headers }); 
       const url = locationUrl; 

       this.http.put(url, reader.result, options).subscribe(res => { 
        observer.next(res); 
       }, (err) => { 
        observer.next({}); 
       }); 
      }; 

      reader.readAsArrayBuffer(file); 

如果有人有一些线索..

+0

你使用的是什么GAPI版本?此外,GAPI似乎正在使用sreams来上传NodeJS中的ifles。你可以试试[this](https://github.com/dominictarr/browser-stream) –

+0

应该是最新版本,你在哪里找到关于使用流(套接字)的文档? –

+0

[Here](https://developers.google。com/drive/v3/web/manage-uploads),查看NodeJS示例。 –

回答

1

您必须使用XMLHttpRequest来创建跨源HTTP请求。 gapi客户端不支持XMLHttpRequest。 (but there is this pull request that's been open for a while)尽管您并未在初始请求中发送文件二进制数据,但您必须将XMLHttpRequest用于文件上传的初始和请求,以便返回的位置url提供适当的响应标头(Access-Control-允许来源:YOUR_URL)并满足CORS要求。

这是一个很棒的tutorial about CORS and XMLHttpRequest,它可能在转换您的请求时很有用。

您可以使用您链接到的页面中描述的请求信息。 This example shows the request info,但不提供有关获取认证令牌的任何信息。 But this example does!

我可以使用下面的代码成功上传的文件:

const file = new File(['Hello, world!'], 'hello world.txt', { type: 'text/plain;charset=utf-8' }); 
const contentType = file.type || 'application/octet-stream'; 
const user = gapi.auth2.getAuthInstance().currentUser.get(); 
const oauthToken = user.getAuthResponse().access_token; 
const initResumable = new XMLHttpRequest(); 
initResumable.open('POST', 'https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable', true); 
initResumable.setRequestHeader('Authorization', 'Bearer ' + oauthToken); 
initResumable.setRequestHeader('Content-Type', 'application/json'); 
initResumable.setRequestHeader('X-Upload-Content-Length', file.size); 
initResumable.setRequestHeader('X-Upload-Content-Type', contentType); 
initResumable.onreadystatechange = function() { 
    if(initResumable.readyState === XMLHttpRequest.DONE && initResumable.status === 200) { 
    const locationUrl = initResumable.getResponseHeader('Location'); 
    const reader = new FileReader(); 
    reader.onload = (e) => { 
     const uploadResumable = new XMLHttpRequest(); 
     uploadResumable.open('PUT', locationUrl, true); 
     uploadResumable.setRequestHeader('Content-Type', contentType); 
     uploadResumable.setRequestHeader('X-Upload-Content-Type', contentType); 
     uploadResumable.onreadystatechange = function() { 
     if(uploadResumable.readyState === XMLHttpRequest.DONE && uploadResumable.status === 200) { 
      console.log(uploadResumable.response); 
     } 
     }; 
     uploadResumable.send(reader.result); 
    }; 
    reader.readAsArrayBuffer(file); 
    } 
}; 

// You need to stringify the request body containing any file metadata 

initResumable.send(JSON.stringify({ 
    'name': file.name, 
    'mimeType': contentType, 
    'Content-Type': contentType, 
    'Content-Length': file.size 
})); 

但有对付这一切都在这里一个更强大的回购:https://github.com/googledrive/cors-upload-sample

+0

谢谢你,你应该得到赏金。我做了同样的事情,但最后的角度$ http服务给我一些CORS错误。可能我搞砸了一些http头,而剩下的驱动器拒绝我上传文件。 –

+0

在Angular http服务中添加了一个额外的答案,而不是普通的xhr –

0

这是BMcV解决方案翻译到角度http服务。

const contentType = file.type || 'application/octet-stream'; 
const baseRoot = gapi['config'].get('googleapis.config').root; 

const reader = new FileReader(); 

reader.onload = (e) => { 

    const authHeader = `Bearer ${this.auth.currentUser.get().getAuthResponse().access_token}`; 

    const metadataHeaders = { 
     'Authorization': authHeader, 
     'Content-Type': 'application/json', 
     'X-Upload-Content-Length': file.size, 
     'X-Upload-Content-Type': contentType 
    }; 
    const metadataOptions = new RequestOptions({ headers: new Headers(metadataHeaders) }); 

    const url = `${baseRoot}/upload/drive/v3/files?uploadType=resumable`; 

    const metadata = { 
     'name': file.name, 
     'mimeType': contentType, 
     'Content-Type': contentType, 
     'Content-Length': file.size 
    }; 

    this.http.post(url, metadata, metadataOptions).subscribe(metadataRes => { 

     const locationUrl = metadataRes.headers.get('Location'); 

     const uploadHeaders = { 
      'Content-Type': contentType, 
      'X-Upload-Content-Type': contentType 
     }; 
     const uploadOptions = new RequestOptions({ headers: new Headers(uploadHeaders) }); 

     this.http.put(locationUrl, reader.result, uploadOptions).subscribe(uploadRes => { 
      console.log(uploadRes.json()); 
     }); 
    }, (err) => { 
     console.error(err); 
    }); 
}; 
reader.readAsArrayBuffer(file); 
相关问题