Hochladen von base64-codiertem Image auf Amazon S3 über Node.js.


98

Gestern habe ich eine Deep-Night-Codierungssitzung durchgeführt und eine kleine node.js / JS-App (eigentlich CoffeeScript, aber CoffeeScript ist nur JavaScript, also sagen wir JS) erstellt.

Was ist das Ziel:

  1. Der Client sendet eine Canvas-Datauri (PNG) an den Server (über socket.io).
  2. Server lädt Bild auf Amazon S3 hoch

Schritt 1 ist erledigt.

Der Server hat jetzt eine Zeichenfolge a la

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACt...

Meine Frage ist: Was sind meine nächsten Schritte, um diese Daten auf Amazon S3 zu "streamen" / hochzuladen und dort ein tatsächliches Bild zu erstellen?

knox https://github.com/LearnBoost/knox scheint eine großartige Bibliothek zu sein, um etwas in S3 zu setzen, aber was mir fehlt, ist der Klebstoff zwischen der Base64-codierten Bildzeichenfolge und der tatsächlichen Upload-Aktion ?

Alle Ideen, Hinweise und Rückmeldungen sind willkommen.


4
Überprüfen Sie diese Antwort: stackoverflow.com/questions/5867534/…
akirk

Antworten:


206

Für Menschen, die immer noch mit diesem Problem zu kämpfen haben. Hier ist der Ansatz, den ich mit nativem aws-sdk verwendet habe.

var AWS = require('aws-sdk');
AWS.config.loadFromPath('./s3_config.json');
var s3Bucket = new AWS.S3( { params: {Bucket: 'myBucket'} } );

Innerhalb Ihrer Routermethode: - ContentType sollte auf den Inhaltstyp der Bilddatei festgelegt werden

  buf = Buffer.from(req.body.imageBinary.replace(/^data:image\/\w+;base64,/, ""),'base64')
  var data = {
    Key: req.body.userId, 
    Body: buf,
    ContentEncoding: 'base64',
    ContentType: 'image/jpeg'
  };
  s3Bucket.putObject(data, function(err, data){
      if (err) { 
        console.log(err);
        console.log('Error uploading data: ', data); 
      } else {
        console.log('succesfully uploaded the image!');
      }
  });

Die Datei s3_config.json lautet: -

{
  "accessKeyId":"xxxxxxxxxxxxxxxx",
  "secretAccessKey":"xxxxxxxxxxxxxx",
  "region":"us-east-1"
}

2
[MissingRequiredParameter: Fehlender erforderlicher Schlüssel 'Schlüssel' in Parametern]
Nichole A. Miler

1
Schlüssel: req.body.userId Ich habe userId als Schlüssel für Post-Daten verwendet ... es war lange zurück ... aber Sie können jede Zeichenfolge als Schlüssel deklarieren. Um sicherzustellen, dass bereits vorhandene Dateien nicht überschrieben werden, behalten Sie den Schlüssel eindeutig bei.
Divyanshu Das

@ Divyanshu Danke für dieses nützliche Beispiel. Ich habe zwei Zweifel: How to make S3 generates a unique KEY to prevent from overriding files?und If I don't set the ContentType, when I download the files I won't be able to get the correct file?ich meine, ich werde so eine beschädigte Datei bekommen? Danke im Voraus!
Alexventuraio

2
@ Marklar Standortpfad ist im Grunde der Schlüssel - z. B. wenn Ihr Bucket-Name - Bucketone und der Schlüsselname xyz.png ist, dann ist der Dateipfad Bucketone.s3.amazonaws.com/xyz.png
Divyanshu Das

2
@ Divyanshu Danke für diese tolle Antwort! Es hat mir sehr geholfen. Ich denke jedoch, dass dies ContentEncoding: 'base64'nicht korrekt ist, da die new Buffer(..., 'base64')Base64-codierte Zeichenfolge in ihre binäre Darstellung dekodiert wird.
Shuhei Kagawa

17

ok, dies ist die Antwort, wie Leinwanddaten in einer Datei gespeichert werden

Im Grunde geht es so in meinem Code

buf = new Buffer(data.dataurl.replace(/^data:image\/\w+;base64,/, ""),'base64')


req = knoxClient.put('/images/'+filename, {
             'Content-Length': buf.length,
             'Content-Type':'image/png'
  })

req.on('response', (res) ->
  if res.statusCode is 200
      console.log('saved to %s', req.url)
      socket.emit('upload success', imgurl: req.url)
  else
      console.log('error %d', req.statusCode)
  )

req.end(buf)

1
Das Pufferobjekt löst den Fehler "Puffer nicht definiert" aus. Können Sie mir eine Lösung dafür geben?
NaveenG

Ich bekomme auch den gleichen Fehler. Sie haben eine Lösung oder nicht
Krishna

1
@NaveenG Dies ist ein Knotenbeispiel. Vielleicht verwenden Sie einfaches JS?
Pointi

7

Hier ist der Code aus einem Artikel, auf den ich gestoßen bin und der unten veröffentlicht wurde:

const imageUpload = async (base64) => {

  const AWS = require('aws-sdk');

  const { ACCESS_KEY_ID, SECRET_ACCESS_KEY, AWS_REGION, S3_BUCKET } = process.env;

  AWS.config.setPromisesDependency(require('bluebird'));
  AWS.config.update({ accessKeyId: ACCESS_KEY_ID, secretAccessKey: SECRET_ACCESS_KEY, region: AWS_REGION });

  const s3 = new AWS.S3();

  const base64Data = new Buffer.from(base64.replace(/^data:image\/\w+;base64,/, ""), 'base64');

  const type = base64.split(';')[0].split('/')[1];

  const userId = 1;

  const params = {
    Bucket: S3_BUCKET,
    Key: `${userId}.${type}`, // type is not required
    Body: base64Data,
    ACL: 'public-read',
    ContentEncoding: 'base64', // required
    ContentType: `image/${type}` // required. Notice the back ticks
  }

  let location = '';
  let key = '';
  try {
    const { Location, Key } = await s3.upload(params).promise();
    location = Location;
    key = Key;
  } catch (error) {
  }

  console.log(location, key);

  return location;

}

module.exports = imageUpload;

Lesen Sie mehr: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property

Credits: https://medium.com/@mayneweb/upload-a-base64-image-data-from-nodejs-to-aws-s3-bucket-6c1bd945420f


3

Die akzeptierte Antwort funktioniert hervorragend, aber wenn jemand eine Datei anstelle von nur Bildern akzeptieren muss, funktioniert dieser reguläre Ausdruck hervorragend:

/^data:.+;base64,/

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.