2017-09-11 41 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); 
相關問題