Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I upload a base64 encoded image (string) directly to a Google Cloud Storage bucket using Node.js?

Currently, I am using the @google-cloud/storage NPM package to upload a file directly to a Google Cloud Storage bucket. This requires some trickery as I only have the image's base64 encoded string. I have to:

  • Decode the string
  • Save it as a file
  • Send the file path to the below script to upload to Google Cloud Storage
  • Delete the local file

I'd like to avoid storing the file in the filesystem altogether since I am using Google App Engine and I don't want to overload the filesystem / leave junk files there if the delete operation doesn't work for whatever reason. This is what my upload script looks like right now:

// Convert the base64 string back to an image to upload into the Google Cloud Storage bucket var base64Img = require('base64-img'); var filePath = base64Img.imgSync(req.body.base64Image, 'user-uploads', 'image-name');  // Instantiate the GCP Storage instance var gcs = require('@google-cloud/storage')(),     bucket = gcs.bucket('google-cloud-storage-bucket-name');  // Upload the image to the bucket bucket.upload(__dirname.slice(0, -15) + filePath, {     destination: 'profile-images/576dba00c1346abe12fb502a-original.jpg',     public: true,     validation: 'md5' }, function(error, file) {      if (error) {         sails.log.error(error);     }      return res.ok('Image uploaded'); }); 

Is there anyway to directly upload the base64 encoded string of the image instead of having to convert it to a file and then upload using the path?

like image 523
JackH Avatar asked Mar 18 '17 19:03

JackH


People also ask

How do I upload base64 image to Firebase storage?

putString(your_base64_image, 'base64', {contentType:'image/jpg'}); Make sure to pass the metadata {contentType:'image/jpg'} as the third parameter (optional) to the function putString in order for you to retrieve the data in an image format. or simply put: uploadTask = firebase.

How do I upload a file to Google bucket?

In the Google Cloud console, go to the Cloud Storage Buckets page. In the list of buckets, click on the name of the bucket that you want to upload an object to. In the Objects tab for the bucket, either: Drag and drop the desired files from your desktop or file manager to the main pane in the console.

Is there anyway to directly upload the Base64 encoded string of image?

Is there anyway to directly upload the base64 encoded string of the image instead of having to convert it to a file and then upload using the path? Show activity on this post. The solution, I believe, is to use the file.createWriteStream functionality that the bucket.upload function wraps in the Google Cloud Node SDK.

How do I upload a string to cloud storage?

If a Blob, File, or Uint8Array isn't available, you can use the putString () method to upload a raw, base64, base64url, or data_url encoded string to Cloud Storage. Learn more about the tree-shakeable Web v9 modular SDK and upgrade from version 8.

How to save a string as a file in Google Cloud Storage?

If you want to save a string as a file in Google Cloud Storage, you can do it easily using the file.save method: Show activity on this post. :) what an issue !! Have tried it and got the issue Image has uploaded on firebase Storage but not download and just loader is moving around and around...

What is add file metadata cloud storage for Firebase?

Add File Metadata Cloud Storage for Firebase allows you to quickly and easily upload files to a Cloud Storage bucket provided and managed by Firebase. Note: By default, a Cloud Storage bucket requires Firebase Authentication to perform any action on the bucket's data or files.


2 Answers

The solution, I believe, is to use the file.createWriteStream functionality that the bucket.upload function wraps in the Google Cloud Node SDK.

I've got very little experience with streams, so try to bear with me if this doesn't work right off.

First of all, we need take the base64 data and drop it into a stream. For that, we're going to include the stream library, create a buffer from the base64 data, and add the buffer to the end of the stream.

var stream = require('stream'); var bufferStream = new stream.PassThrough(); bufferStream.end(Buffer.from(req.body.base64Image, 'base64')); 

More on decoding base64 and creating the stream.

We're then going to pipe the stream into a write stream created by the file.createWriteStream function.

var gcs = require('@google-cloud/storage')({   projectId: 'grape-spaceship-123',   keyFilename: '/path/to/keyfile.json' });  //Define bucket. var myBucket = gcs.bucket('my-bucket'); //Define file & file name. var file = myBucket.file('my-file.jpg'); //Pipe the 'bufferStream' into a 'file.createWriteStream' method. bufferStream.pipe(file.createWriteStream({     metadata: {       contentType: 'image/jpeg',       metadata: {         custom: 'metadata'       }     },     public: true,     validation: "md5"   }))   .on('error', function(err) {})   .on('finish', function() {     // The file upload is complete.   }); 

Info on file.createWriteStream, File docs, bucket.upload, and the bucket.upload method code in the Node SDK.

So the way the above code works is to define the bucket you want to put the file in, then define the file and the file name. We don't set upload options here. We then pipe the bufferStream variable we just created into the file.createWriteStream method we discussed before. In these options we define the metadata and other options you want to implement. It was very helpful to look directly at the Node code on Github to figure out how they break down the bucket.upload function, and recommend you do so as well. Finally, we attach a couple events for when the upload finishes and when it errors out.

like image 158
forrestmid Avatar answered Sep 30 '22 12:09

forrestmid


Posting my version of the answer in response to @krlozadan 's request above:

// Convert the base64 string back to an image to upload into the Google Cloud Storage bucket var mimeTypes = require('mimetypes');  var image = req.body.profile.image,     mimeType = image.match(/data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,.*/)[1],     fileName = req.profile.id + '-original.' + mimeTypes.detectExtension(mimeType),     base64EncodedImageString = image.replace(/^data:image\/\w+;base64,/, ''),     imageBuffer = new Buffer(base64EncodedImageString, 'base64');  // Instantiate the GCP Storage instance var gcs = require('@google-cloud/storage')(),     bucket = gcs.bucket('my-bucket');  // Upload the image to the bucket var file = bucket.file('profile-images/' + fileName);  file.save(imageBuffer, {     metadata: { contentType: mimeType },     public: true,     validation: 'md5' }, function(error) {      if (error) {         return res.serverError('Unable to upload the image.');     }      return res.ok('Uploaded'); }); 

This worked just fine for me. Ignore some of the additional logic in the first few lines as they are only relevant to the application I am building.

like image 40
JackH Avatar answered Sep 30 '22 14:09

JackH