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

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

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

I would like to avoid storing the file in the file system in general, since I use the Google App Engine, and I do not want to overload the file system / leave unnecessary files there if the delete operation does not work for any reason. Here's what my script loading 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 it necessary in any case to directly load the base64 encoded image string instead of converting it to a file and then uploading using the path?

+5
source share
2 answers

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

I have very little experience with threads, so try to carry me if this does not work.

First of all, we need to take the base64 data and transfer it to the stream. To do this, we are going to include the stream library, create a buffer from base64 data and add a buffer to the end of the stream.

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

Learn more about base64 decoding and stream creation .

We are going to transfer the stream to the recording 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. }); 

Information about file.createWriteStream , File documents , bucket.upload and bucket.upload method code in Node SDK .

Thus, how the above code works, you need to determine the bucket in which you want to put the file, and then determine the file and file name. We do not set download options here. Then we pass the bufferStream variable that we just created into the file.createWriteStream method that we discussed earlier. In these options, we define the metadata and other parameters that you want to implement. It was very helpful to take a look at the Node code on Github to find out how they break the bucket.upload function and recommend that you do this as well. Finally, we attach a couple of events when the download ends and when it crashes.

+13
source

Posting my version of the response in response to the @krlozadan 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'); }); 

It worked fine for me. Ignore some additional logic in the first few lines, as they apply only to the application I am creating.

+1
source

Source: https://habr.com/ru/post/1265653/


All Articles