Carga de una imagen codificada en base64 a Amazon S3 a través de Node.js

99

Ayer hice una sesión de codificación nocturna profunda y creé una pequeña aplicación node.js / JS (bueno, en realidad CoffeeScript, pero CoffeeScript es solo JavaScript, así que digamos JS).

cual es el objetivo:

  1. el cliente envía un datauri de lienzo (png) al servidor (a través de socket.io)
  2. el servidor carga la imagen en amazon s3

el paso 1 está hecho.

el servidor ahora tiene una cadena a la

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

mi pregunta es: ¿cuáles son mis próximos pasos para "transmitir" / cargar estos datos en Amazon S3 y crear una imagen real allí?

knox https://github.com/LearnBoost/knox parece una biblioteca increíble para PONER algo a S3, pero lo que me falta es el pegamento entre la cadena de imagen codificada en base64 y la acción de carga real .

Todas las ideas, sugerencias y comentarios son bienvenidos.

Franz Enzenhofer
fuente
4
Compruebe esta respuesta: stackoverflow.com/questions/5867534/…
akirk

Respuestas:

209

Para las personas que todavía luchan con este problema. Este es el enfoque que utilicé con aws-sdk nativo.

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

dentro de su método de enrutador: - ContentType debe establecerse en el tipo de contenido del archivo de imagen

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

El archivo s3_config.json es: -

{
  "accessKeyId":"xxxxxxxxxxxxxxxx",
  "secretAccessKey":"xxxxxxxxxxxxxx",
  "region":"us-east-1"
}
Divyanshu Das
fuente
2
[MissingRequiredParameter: Falta la clave obligatoria 'Key' en los parámetros]
Nichole A. Miler
1
Clave: req.body.userId Usé userId como clave en los datos de publicación ... fue hace mucho tiempo ... pero puede declarar cualquier cadena como clave. Para asegurarse de que los archivos ya presentes no se sobrescriban, mantenga la clave única.
Divyanshu Das
@Divyanshu Gracias por tan útil ejemplo. Tengo dos dudas: How to make S3 generates a unique KEY to prevent from overriding files?y If I don't set the ContentType, when I download the files I won't be able to get the correct file?quiero decir, ¿obtendré un archivo tan dañado? ¡Gracias por adelantado!
alexventuraio
2
La ruta de ubicación de @Marklar es básicamente clave, por ejemplo, si el nombre de su depósito es - bucketone y el nombre de la clave es xyz.png, la ruta del archivo será bucketone.s3.amazonaws.com/xyz.png
Divyanshu Das
2
@Divyanshu ¡Gracias por esta gran respuesta! Me ayudó mucho. Sin embargo, creo que ContentEncoding: 'base64'no es correcto porque new Buffer(..., 'base64')decodifica una cadena codificada en base64 en su representación binaria.
Shuhei Kagawa
17

ok, esta es la respuesta a cómo guardar datos de lienzo en un archivo

básicamente se pierde así en mi código

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
fuente
1
El objeto Buffer arrojará un error "Buffer not define".
NaveenG
También recibo el mismo error. tienes alguna solución o no
Krishna
1
@NaveenG Este es un ejemplo de nodo, ¿tal vez estás usando JS simple?
Pointi
7

Aquí está el código de un artículo que encontré, que publiqué a continuación:

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;

Leer más: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property

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

Harvey
fuente
4

La respuesta aceptada funciona muy bien, pero si alguien necesita aceptar cualquier archivo en lugar de solo imágenes, esta expresión regular funciona muy bien:

/^data:.+;base64,/

Ms01
fuente