Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
420 views
in Technique[技术] by (71.8m points)

javascript - Angular 2+ HTTP POST and GDrive API. Resumable file upload with name

I am trying to upload files to Google Drive in Angular 2. So far I am able to upload files, but without title and they are "Untitled"

Here is code to do that:

gDriveUploader(file): Promise<any> {
let authToken = tokenHere;
const url = `https://www.googleapis.com/upload/drive/v2/files/`
    let formData:FormData = new FormData();
    formData.append('title', file, file.name);
    let headers = new Headers({
      'Authorization': 'Bearer ' + authToken
    });
    headers.append('Accept', file.type);
    let options = new RequestOptions ({ 
      headers: headers,
    });

    console.log('OPTIONS: ', options)

    return this.http.post(`${url}`, formData, options)
        .toPromise()
           .then(response => response.json())
           .catch(e=>console.log(e));
}

I know, that in order to send metadata with file, I have to add this metadata to Request body and use at multipart or resumable upload types. But here I faced issue after issue and just can't make it properly.

I completely messed up. Here is on of my approaches with resumable upload type:

gDriveUploader(file): Promise<any> {
let authToken = token;
const url = `https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable`
    console.log('FILE TO UPLOAD: ', file)
    let formData:FormData = new FormData();
    formData.append('name', file, file.name);
    let headers = new Headers({
      'Authorization': 'Bearer ' + authToken,
      'Content-Type': 'application/json; charset=UTF-8', //if remove "Bad Content" Error
      //'Content-Length': file.size, not sure if this one right?
    });
    let options = new RequestOptions ({ 
      headers: headers,
    });

    return this.http.post(`${url}`, formData, options)
        .toPromise()
           .then(response => response.json())
           .catch(e=>console.log(e));
}

that's not only two of my approaches...

According to Drive API for resumable upload:

POST https://www.googleapis.com/drive/v3/files?uploadType=resumable 

HTTP/1.1
Authorization: Bearer [YOUR_AUTH_TOKEN]
Content-Length: 38
Content-Type: application/json; charset=UTF-8
X-Upload-Content-Type: image/jpeg
X-Upload-Content-Length: 2000000

What is Content-Length: 38? it's file length and I can just use file.size?

With multipart I can't figure out how to add those boundary separator in the request.

I saw some Q and A, that multipart were not supported by Angular, but that was 1-2 year ago. What about now?

Can I somehow use resumable upload to GDrive with additional file metadata using standard Angular features?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

So. A bit more research on how API works. I came up with the following solution for resumable file upload. Main Idea, that first time I have to make a request and "set metadata" for my file and get response with the link, where to upload the file. And this link came as one of the response header called location.

Here is fully working code. Just pass File object to the first function.

I just quickly made 2 functions for this. First one will set metadata (just name) and call second function to upload just binary data.

gDriveUploader(file): Promise<any> {
  let authToken = token
  const url = `https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable`
      let headers = new Headers({
        'Authorization': 'Bearer ' + authToken,
        'Content-Type': 'application/json; charset=UTF-8',
      });
      let options = new RequestOptions ({ 
        headers: headers,
      });
      return this.http.post(`${url}`, {name: file.fullName}, options) //just set the name
          .toPromise()
            .then(response => this.gDriveUploadFile(file, response.headers.get('location'))) //call second function to upload `file` to proper URI from response
            .then(response => {
                let id = response.json().id //parse id of uploaded file
                let resp = {fileName: file.fullName, fileType: file.fileType, fileSize: file.size, fileId: id} //create an object with file file properties, if you need that
                return resp // return object back to function that called this service
            })
            .catch(e=>console.log(e));
  }

Second function to upload data:

gDriveUploadFile(file, url): Promise<any> { //file and url we got from first func
  let authToken = token
      let headers = new Headers({
        'Authorization': 'Bearer ' + authToken,
        'Content-Type': 'application/json; charset=UTF-8',
        'X-Upload-Content-Type': file.type
      });
      let options = new RequestOptions ({ 
        headers: headers,
      });
      return this.http.post(`${url}`, file, options) //call proper resumable upload endpoint and pass just file as body
          .toPromise()
  }

Maybe solution not ideal, so far I do not handle errors here and do not use resumable features like uploading by chunks, just upload file at once. But hopefully if someone else stuck with GDrive uploading can get an idea.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...