Téléchargement d'une image encodée en base64 sur Amazon S3 via Node.js

99

Hier, j'ai fait une session de codage nocturne profonde et créé une petite application node.js / JS (enfin CoffeeScript, mais CoffeeScript est juste du JavaScript, disons JS).

quel est le but:

  1. le client envoie un canevas datauri (png) au serveur (via socket.io)
  2. le serveur télécharge l'image sur amazon s3

l'étape 1 est terminée.

le serveur a maintenant une chaîne a la

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

ma question est: quelles sont mes prochaines étapes pour «diffuser» / télécharger ces données sur Amazon S3 et y créer une image réelle?

knox https://github.com/LearnBoost/knox semble être une bibliothèque géniale pour METTRE quelque chose dans S3, mais ce qui me manque, c'est le lien entre la chaîne d'image encodée en base64 et l'action de téléchargement réelle ?

Toutes les idées, pointeurs et commentaires sont les bienvenus.

Franz Enzenhofer
la source
4
Vérifiez cette réponse: stackoverflow.com/questions/5867534/…
akirk

Réponses:

209

Pour les personnes qui sont encore aux prises avec ce problème. Voici l'approche que j'ai utilisée avec aws-sdk natif.

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

à l'intérieur de votre méthode de routeur: - ContentType doit être défini sur le type de contenu du fichier image

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

Le fichier s3_config.json est: -

{
  "accessKeyId":"xxxxxxxxxxxxxxxx",
  "secretAccessKey":"xxxxxxxxxxxxxx",
  "region":"us-east-1"
}
Divyanshu Das
la source
2
[MissingRequiredParameter: Clé requise manquante 'Key' dans les paramètres]
Nichole A. Miler
1
Clé: req.body.userId J'ai utilisé userId comme clé dans les données de publication ... il y a longtemps ... mais vous pouvez déclarer n'importe quelle chaîne comme clé. Pour vous assurer que les fichiers déjà présents ne sont pas écrasés, gardez la clé unique.
Divyanshu Das
@Divyanshu Merci pour cet exemple utile. J'ai deux doutes: How to make S3 generates a unique KEY to prevent from overriding files?et If I don't set the ContentType, when I download the files I won't be able to get the correct file?je veux dire, j'obtiendrai un fichier aussi corrompu? Merci d'avance!
alexventuraio
2
Le chemin de l'emplacement @Marklar est fondamentalement la clé - par exemple, si le nom de votre bucket est - bucketone et le nom de la clé est xyz.png, le chemin du fichier sera bucketone.s3.amazonaws.com/xyz.png
Divyanshu Das
2
@Divyanshu Merci pour cette excellente réponse! Cela m'a beaucoup aidé. Cependant, je pense que ce ContentEncoding: 'base64'n'est pas correct car new Buffer(..., 'base64')décode la chaîne codée en base64 dans sa représentation binaire.
Shuhei Kagawa
17

ok, celui-ci est la réponse comment enregistrer les données du canevas dans un fichier

fondamentalement ça se détache comme ça dans mon 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)
Franz Enzenhofer
la source
1
L'objet Buffer lancera une erreur "Buffer not define" pouvez-vous me donner une solution pour cela.
NaveenG
J'obtiens également la même erreur. vous avez une solution ou pas
Krishna
1
@NaveenG Ceci est un exemple de nœud, peut-être que vous utilisez JS brut?
Pointi
7

Voici le code d'un article que j'ai rencontré, posté ci-dessous:

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;

En savoir plus: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property

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

Harvey
la source
4

La réponse acceptée fonctionne très bien, mais si quelqu'un a besoin d'accepter un fichier au lieu de seulement des images, cette expression rationnelle fonctionne très bien:

/^data:.+;base64,/

Ms01
la source