Perform resumable uploads using google-cloud-node

984 views Asked by At

This code works great for normal uploads, but I am wondering how the resumable upload works when, for example, the user loses connection in the middle of a large upload. Is setting resumable to true in the writeStream options the only thing necessary for this to work?

Ive read through this link on performing resumable uploads, but it seems, that the createWriteStream function should encapsulate this behavior.

I have tried testing this out by turning off my wifi in the middle of an upload, but the time it takes to finish uploading once I resume upload is the same as an uninterrupted upload which is why i'm not sure if this is actually working.

Any help or explanation is appreciated, let me know if I can clarify anything.

stream = remoteFile.createWriteStream({gzip: true, resumable: true, metadata: {contentType: file.mimetype} });

stream.on('error', (err: any) => {
    next(err);
    res.status(400).send('err');
});

stream.on('finish', () => {
    res.status(200).send('Success!');
});

stream.end(file.buffer);

1

There are 1 answers

1
PandaScript On

I didn't trust the resumable metadata option as the only way to make the upload resumable so I followed the instructions here. I have attached my code below. This is for a single request resumable upload, NOT multiple chunk.

First I send a POST request to the bucket upload url to receive the resumable session uri

let url = 'https://www.googleapis.com/upload/storage/v1/b/bucketname/o?uploadType=resumable&name=testing';

let objBody = JSON.stringify({'metadata': {'someDataPoint': req.body.someDataPoint}});

let contentLength: number = Buffer.byteLength(objBody, 'utf-8');

let options = {
  url: url,
  method: 'POST',
  body: objBody,
  headers: {
    'Content-Length': contentLength,
    'X-Upload-Content-Type': req.file.mimetype,
    'X-Upload-Content-Length': req.file.size,
    'Content-Type': 'application/json; charset=UTF-8'
  }
};

request(options, (error: any, response: any, body: any, stat: any) => {

    if (response && response.statusCode === 200) {
        // send response.headers.location to next function for put request

    } else {
        console.log('err!', error);
        res.status(400).send(error);
    }

});

Then I send a PUT request to the received session uri with my file data

let url = resumableUri;

let options = {
    url: url,
    method: 'PUT',
    body: req.file.buffer,
    headers: {
        'Content-Length': req.file.size,
        'Content-Type': req.file.mimetype,
    }
};

request(options, (error: any, response: any, body: any, stat: any) => {

  if (response && response.statusCode === 200) {
      res.status(200).send('ok');
  } else if (response && response.statusCode >= 500) {
      // send request to resume upload
  } else {
      // try upload again
  }

});