Using Angular 2+ to make HTTP POST requests and interact with the GDrive API. Implementing resumable file uploads

I am currently facing a challenge with uploading files to Google Drive using Angular 2. I have managed to upload files successfully, but they end up being labeled as "Untitled" without any title.

Below is the code snippet I am using for the upload process:

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));
}

Despite my attempts to include metadata in the Request body for proper file handling during uploads, I am encountering multiple issues with the process.

I recently tried implementing a resumable upload type, and here is an excerpt from my approach:

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',
    });
    let options = new RequestOptions ({ 
      headers: headers,
    });

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

However, this is just one of my failed attempts...

As per the Drive API documentation for resumable uploads:

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 exactly does Content-Length: 38 signify? Can I use file.size instead?

Regarding multipart uploads, I am struggling to understand how to add boundary separators to the request.

I recall reading that Angular did not support multipart uploads in the past, but has this changed recently?

Is there a way to utilize standard Angular features for enabling resumable uploads to Google Drive along with additional file metadata?

Answer №1

After delving further into how APIs function, I developed a solution for resumable file uploads. The main concept involves making an initial request to "set metadata" for the file and receiving a response containing a link where the file can be uploaded. This link is provided in one of the response headers labeled as location.

Below is a fully functional code snippet. Simply pass a File object to the first function.

I quickly created two functions for this purpose. The first function sets metadata (just the name) and then calls the second function to upload the 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));
  }

The second function handles the actual uploading of 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()
  }

This solution may not be perfect as it does not handle errors or utilize resumable features such as chunked uploading. However, it can serve as a starting point for those facing challenges with GDrive file uploads.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring and extracting values from nested arrays of objects in JavaScript and React

Hey there, I am having trouble getting the data from the backend server to display on a chart library. Can you please take a look at my code and help me out? const data = [ { id: "americano", data: [{x: "10",y: 10,}, {x: &quo ...

Having difficulty updating the value of a FieldArray with setFieldValue in Formik

Thank you for taking the time to read this. I am currently working on creating a form using Formik that involves nesting a FieldArray within another FieldArray. Oddly enough, setFieldValue seems to be functioning correctly as I can log the correct values ...

Utilize a universal type for the property name in TypeScript

In my code, I am using an enum as a propName for an object-like type. export enum WeaponClass { smallLaser = "smallLaser", } export type WeaponType = { [propName in WeaponClass]: number }; const weapons: WeaponType = { [WeaponClass.smallLase ...

Tips for dividing an array based on a defined regex pattern in JavaScript

I want to split a string of text into an array of sentences while preserving the punctuation marks. var text = 'This is the first sentence. This is another sentence! This is a question?' var splitText = text.split(/\b(?<=[.!?])/); split ...

Capture a fragment of a scene and convert it into a unique texture using THREE.JS

I'm interested in creating a texture of a specific area in my scene, similar to the example shown in the official documentation for three.js framebuffer here. As I examine the code provided, there's one particular aspect that's unclear to me ...

Update the displayed locations on Google Maps by fetching and displaying marker data

I am able to retrieve and display information from my MySQL table, but I need assistance with refreshing this data every 5 seconds using my current code. The data being shown is not extensive, just about 5 or 8 markers at a time. Below is the code I curren ...

React-router-sitemap lacks a definition for 'Require'

According to the official documentation here, this is how the sitemap-builder.js file should be structured: require('babel-register'); const router = require('./router').default; const Sitemap = require('../').default; ( ...

Guide on updating a single element in a Firebase array

I have an array stored in my firebase database, structured like this: matches:[ {match:{id:1,data:...}}] I am looking for a way to update just one specific item within this array. Let's say I want to locate the match with the ID of 32 and modify its ...

Exploring the Haversine Formula and Geolocation Integration in AngularJS

I am currently developing an application that will organize locations based on either name or distance from the user. Everything is functioning properly except for retrieving the distance. I believe I should be able to obtain the user's coordinates th ...

Exploring Json parsing in Python with Django

I am currently using Django for my web application. I am facing an issue where I cannot access Nodes and edges by calling decoded_data['nodes']. Instead, I am encountering the error message: 'NoneType' object is not subscriptable Thi ...

The automated test locator in Angular using Protractor is failing to function

I am facing a challenge with my angular web application as there are some elements that are difficult to interact with. One specific element is a checkbox that needs to be checked during testing: ` <div class="row form-group approval_label"> < ...

Differences between JSX and creating instances of component classes

Could someone please clarify the distinction between the following two statements? let instance1 = new CustomComponent(); and let instance2 = <CustomComponent /> When checking in the Chrome debugger, I see the following: for instance1 CustomComp ...

Learn how to monitor and analyze hard drive usage and statistics on Windows and Mac systems by utilizing node.js or electronjs

Is there a way to retrieve hard disk utilization, idle time, and HDD type using JavaScript specifically for Windows and MacOS operating systems? I have access to the nodejs and electron API for my application. I have been struggling to find any API or np ...

Create a new object containing a series of function expressions, but exclude the first function parameter

In my current setup, I have a variable called storePattern const storePattern = { state: { }, mutations: { }, actions: {}, modules: { modal: { actions: { openModal(store, name: string): boolean { console.log('Op ...

Is there a way to access the original query string without it being automatically altered by the browser?

I'm currently encountering an issue with query strings. When I send an activation link via email, the link contains a query string including a user activation token. Here's an example of the link: http://localhost:3000/#/activation?activation_cod ...

Having trouble with ngx-pagination's next page button not responding when clicked?

I am experiencing issues with pagination. The next page button does not function as expected, and clicking on the page number also does not work. Below is the code snippet and a Demo link for your reference. HTML <table mat-table [dataSou ...

Limit the length of text using jQuery by specifying the maximum pixel width

Trying to utilize jQuery for a quick function that calculates the pixel width of a string on an HTML page and then shortens the string until it reaches a desired pixel width... Unfortunately, I'm encountering issues with this process as the text is n ...

The persistent Expo in-app purchase sandbox pop-up continues to plague, hindering the completion of the test purchase

After creating my app using Expo and integrating Revenuecat for payments, I encountered an issue while testing it. Whenever I try to subscribe, the purchase popup keeps reappearing in Sandbox mode even after clicking 'Done'. Despite entering vali ...

What is the Angular lifecycle event that occurs after all child components have been initialized?

Seeking help with implementing a concept for the following scenario: I have a parent search component containing several child components for displaying facets and search results. I want to automatically trigger a search once the application has finished ...

Is it possible to use a single function to both set the state and return JSX?

I'm currently grappling with creating a function that, when called, will update the state to an object {item: 'whatever the user types', list: [...list, todo]}. The challenge I'm facing is figuring out how to update the state and return ...