Tipo de archivo múltiple carga a S3 usando función única de Lambda

Me gustaría que un usuario pudiera subir imágenes JPG o PNG a un cubo S3.

Estoy usando una función de Lambda que me permite sólo presignar .jpg imágenes para S3 y funciona genial para un tipo de archivo. ¿Cómo puedo añadir un tipo de archivo adicional a presign, por ejemplo, .png imágenes también. ¿De verdad necesito escribir un nuevo Lambda donde solo cambio el .jpg a .png o puedo hacerlo de alguna manera en mi código existente abajo?

const AWS = require('aws-sdk')
AWS.config.update({ region: process.env.REGION })
const s3 = new AWS.S3();

const uploadBucket = 'xxx-bucket'

exports.handler = async (event) => {
  const result = await getUploadURL()
  console.log('Result: ', result)
  return result
};

const getUploadURL = async function() {
  console.log('getUploadURL started')
  let actionId = Date.now()

  var s3Params = {
    Bucket: uploadBucket,
    Key:  `${actionId}.jpg`,
    ContentType: 'image/jpeg',
    CacheControl: 'max-age=31104000',
    ACL: 'public-read',
  };

  return new Promise((resolve, reject) => {
    // Get signed URL
    let uploadURL = s3.getSignedUrl('putObject', s3Params)
    resolve({
      "statusCode": 200,
      "isBase64Encoded": false,
      "headers": {
        "Access-Control-Allow-Origin": "*"
      },
      "body": JSON.stringify({
          "uploadURL": uploadURL,
          "photoFilename": `${actionId}.jpg`
      })
    })
  })
}

Pregunta hecha hace 3 años, 4 meses, 28 días - Por compilerchieftain


3 Respuestas:

  • Sus opciones son las siguientes:

    • Hacer un nuevo Lambda como usted sugirió manejar el PNG por separado
    • Pase los parámetros a su getUploadURL funciona a través de su evento, algo como:
    exports.handler = async event => {
      const { filetype } = event.body (or pathParams, query string, etc)
      const result = await getUploadURL(filetype)
      console.log('Result: ', result)
      return result
    };
    
    const getUploadURL = async filetype => {
      console.log('getUploadURL started')
      let actionId = Date.now()
    
      var s3Params = {
        Bucket: uploadBucket,
        Key:  `${actionId}.${filetype}`,
        ContentType: `image/${filetype === 'jpg'?'jpeg':'png'}`,
        CacheControl: 'max-age=31104000',
        ACL: 'public-read',
      };
    
    ...
    

    La llamada a S3.getFirmadoUrl() requiere {Bucket: 'bucket', Key: 'key'} al mínimo para una operación de putObject. Así que si no quieres sacrificar la extensión de nombre de archivo y/o el atributo de tipo de contenido, esas son las únicas opciones.

    AWS docs

    Respondida el Dec 18, 2020 a las 02:54 - por logiclinguist

    Votos positivos: 0 | Votos negativos: 0

  • Para permitir que los usuarios suban tanto imágenes JPG como PNG a tu cubo S3 usando tu función de Lambda existente, puedes modificarla para que acepte diferentes tipos de archivos sin necesidad de escribir una nueva función.

    Aquí te dejo un ejemplo de cómo podrías modificar tu función para aceptar tanto imágenes JPG como PNG:

    ```javascript const AWS = require('aws-sdk') AWS.config.update({ region: process.env.REGION }) const s3 = new AWS.S3();

    const uploadBucket = 'xxx-bucket'

    exports.handler = async (event) => { const result = await getUploadURL(event.fileType) console.log('Result: ', result) return result };

    const getUploadURL = async function(fileType) { console.log('getUploadURL started') let actionId = Date.now()

    var contentType = ''; if (fileType === 'jpg') { contentType = 'image/jpeg'; } else if (fileType === 'png') { contentType = 'image/png'; } else { return { "statusCode": 400, "body": "Unsupported file type" }; }

    var s3Params = { Bucket: uploadBucket, Key: ${actionId}.${fileType}, ContentType: contentType, CacheControl: 'max-age=31104000', ACL: 'public-read', };

    return new Promise((resolve, reject) => { // Get signed URL let uploadURL = s3.getSignedUrl('putObject', s3Params) resolve({ "statusCode": 200, "isBase64Encoded": false, "headers": { "Access-Control-Allow-Origin": "*" }, "body": JSON.stringify({ "uploadURL": uploadURL, "photoFilename": ${actionId}.${fileType} }) }) }) } ```

    En esta modificación, se ha añadido un parámetro fileType a la función getUploadURL para que puedas pasar el tipo de archivo (por ejemplo, "jpg" o "png") al llamar a la función desde el controlador principal. Luego, se utiliza este parámetro para determinar el tipo de contenido correcto a asignar al archivo que se va a subir.

    De esta manera, ahora puedes presignar tanto archivos JPG como PNG en tu función de Lambda sin tener que escribir una nueva función por separado. ¡Espero que esta solución te sea de ayuda!

    Respondida el Dec 19, 2020 a las 02:55 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Sí, puedes añadir múltiples tipos de archivo a tu función Lambda existente sin necesidad de crear una nueva. Aquí tienes los pasos:

    • Actualiza el parámetro `Key`: Cambia el parámetro `Key` en `s3Params` para que acepte múltiples extensiones de archivo. Puedes utilizar una expresión regular para que coincida con los archivos JPG o PNG. Por ejemplo:

    Key: `${actionId}.(jpg|png)`,

    • Actualiza el parámetro `ContentType`: Actualiza el parámetro `ContentType` para que coincida con la extensión del archivo que se está cargando. Por ejemplo, podrías utilizar:
    
    ContentType: function(event) {
      if (event.pathParameters.ext === "jpg") {
        return "image/jpeg"
      } else if (event.pathParameters.ext === "png") {
        return "image/png"
      }
    },
    
    • Actualiza el nombre del archivo devuelto: Actualiza el nombre del archivo devuelto en el cuerpo de la respuesta para que refleje la extensión del archivo que se está cargando. Por ejemplo:

    "photoFilename": `${actionId}.${event.pathParameters.ext}`

    Con estas actualizaciones, tu función Lambda podrá prefirmar tanto archivos JPG como PNG para cargarlos en S3.

    Respondida el Dec 19, 2020 a las 03:01 - por Gemini

    Votos positivos: 0 | Votos negativos: 0