5

Derzeit verwende ich das NPM-Paket @google-cloud/storage, um eine Datei direkt in einen Google Cloud Storage-Bucket hochzuladen. Dies erfordert einige Tricks, da ich nur die base64-kodierte Zeichenkette des Bildes habe. Ich muss:Wie lade ich ein base64-kodiertes Bild (String) mit Node.js direkt in einen Google Cloud Storage-Bucket hoch?

  • Decode die Zeichenfolge
  • Speichern als Datei
  • den Dateipfad an den unten Skript zu Google Cloud Storage laden
  • die lokale Datei löschen

Ich möchte es vermeiden, die Datei vollständig im Dateisystem zu speichern, da ich Google App Engine verwende. Ich möchte das Dateisystem nicht überladen/Junk-Dateien dort belassen, wenn der Löschvorgang aus irgendeinem Grund nicht funktioniert. Dies ist, was mein Upload-Skript wie jetzt aussieht:

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

Gibt es trotzdem direkt die Base64-String des Bildes codiert zu laden, anstatt sie in eine Datei umwandeln zu müssen und dann den Pfad laden verwenden?

+0

'bucket.upload' umschließt die' Datei.createWriteStream '-Funktion, so müssen Sie Ihre Base64-Datei Zeichenfolge in den Stream pipe, die von dieser Methode in' Datei' erstellt. Ich würde nur empfehlen, in das Dateisystem zu schreiben und die Verknüpfung nach dem Hochladen aufzuheben. Ich glaube nicht, dass Sie Probleme mit dem Löschen der Dateien haben werden. Ich könnte vielleicht ein Beispiel machen, wenn Sie so geneigt sind. – forrestmid

+0

@forrestmid Wäre wirklich ein Beispiel dafür, wie Sie den 'file.createWriteStream' zum direkten Upload implementieren würden. Vielen Dank! – Nag

Antwort

13

Die Lösung, glaube ich, ist die Verwendung der file.createWriteStream Funktionalität, die die bucket.upload Funktion in das Google Cloud Node SDK umschließt.

Ich habe sehr wenig Erfahrung mit Streams, also versuchen Sie es mit mir zu ertragen, wenn das nicht gleich funktioniert.

Zuerst müssen wir die base64 Daten nehmen und sie in einen Stream fallen lassen. Dazu werden wir die stream-Bibliothek einschließen, einen Puffer aus den base64-Daten erstellen und den Puffer am Ende des Streams hinzufügen.

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

Mehr auf decoding base64 und creating the stream.

Wir werden dann den Stream in einen Schreibstrom leiten, der von der file.createWriteStream-Funktion erstellt wird.

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 auf file.createWriteStream, File docs, bucket.upload und die bucket.upload method code in the Node SDK.

Wie der obige Code funktioniert, definieren Sie den Bucket, in den Sie die Datei einfügen möchten, und definieren Sie dann die Datei und den Dateinamen. Wir legen hier keine Upload-Optionen fest. Wir leiten dann die bufferStream Variable, die wir gerade erstellt haben, in die zuvor besprochene file.createWriteStream Methode. In diesen Optionen definieren wir die Metadaten und andere Optionen, die Sie implementieren möchten. Es war sehr hilfreich, direkt auf die Node code on Github zu schauen, um herauszufinden, wie sie die bucket.upload Funktion zusammenbrechen, und empfehlen Ihnen, dies auch zu tun. Schließlich fügen wir ein paar Ereignisse für das Ende des Uploads und für den Fehler hinzu.

+0

Danke für das Posten! Ich habe tatsächlich etwas Ähnliches gemacht, außer dass ich [file.save()] (https://googlecloudplatform.github.io/google-cloud-node/#/docs/storage/0.8.0/storage/file?method=) verwendet habe Speichern) API, die ein Wraparound von 'createWriteStream' ist. – Nag

+1

@Nag Das funktioniert definitiv! Ich habe diese API gelesen, habe aber nicht bemerkt, dass die Operation mit der übereinstimmt, nach der Sie gesucht haben. Ich bin froh, dass du es herausgefunden hast. – forrestmid

+0

@Nag wie genau hast du das geschafft? Hast du den Quellcode, den wir uns anschauen können ?? Ich kämpfe sehr damit. Ich versuche, eine basis64-codierte Bildzeichenfolge von der Firebase Cloud-Funktion auf Firebase Storage zu laden – krlozadan

1

Posting meine Version der Antwort als Antwort auf @krlozadan ‚s Anfrage über:

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

Das funktionierte für mich ganz gut. Ignorieren Sie einige der zusätzlichen Logik in den ersten Zeilen, da sie nur für die von mir erstellte Anwendung relevant sind.

Verwandte Themen