2017-09-11 1 views
13

Google Api를 통해 Google 드라이브에서 재개 가능한 업로드를 수행하기 위해 this 가이드를 따르려고합니다.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 라이브러리 단지의 FileArray을 jsoing되고이 때문에 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는 NodeJS에 iframe을 업로드하는 데 sream을 사용하는 것으로 보입니다. [this] (https://github.com/dominictarr/browser-stream)로 시도 할 수 있습니다 –

+0

최신 버전이되어야합니다. 스트림 (소켓) 사용에 대한 설명서는 어디에서 찾을 수 있습니까? –

+0

[여기] (https://developers.google.co.kr/drive/v3/web/manage-uploads), NodeJS 예제를 살펴보십시오. –

답변

1

교차 원 HTTP 요청을 작성하려면 XMLHttpRequest를 사용해야합니다. gapi 클라이언트는 XMLHttpRequest를 지원하지 않습니다. (but there is this pull request that's been open for a while) 초기 요청에서 파일 바이너리 데이터를 보내지는 않지만 반환 된 위치에 대해 파일을 업로드하는 위치와 요청에 모두 XMLHttpRequest를 사용해야합니다. url은 적절한 응답 헤더를 제공합니다 (Access-Control- Allow-Origin : 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 
})); 

을하지만, 여기에 모든 처리하기위한보다 강력한 환매 특약이 :이은 BMcV 솔루션 번역 https://github.com/googledrive/cors-upload-sample

+0

감사합니다, 당신은 현상금을받을 자격이 있습니다. 나는 당신이했던 것과 똑같은 짓을했으나 결국 $ HTTP 서비스로 인해 CORS 오류가 발생했습니다. 아마 내가 http-header를 엉망으로 만들었고 드라이브 레스트가 파일 업로드를 거부했다. –

+0

일반 xhr 대신 Angular http 서비스와 함께 아래에 추가 답변이 추가되었습니다. –

0

은 각도 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); 
관련 문제