Как загрузить JPG в AWS Lambda (NodeJS) - PullRequest
0 голосов
/ 22 сентября 2018

Я пытаюсь сделать это:

  1. Внешний интерфейс: настроить файл для загрузки с помощью <input type="file"> и <input type="button" onClick="...">
  2. Объект File извлекается с помощью file[0] иззначение <input type="file">.
  3. Используйте Javascript Fetch api для вызова моего AWS API-шлюза Post API.

Я пробовал оба multipart/form-data и application/json в запросе.

В AWS Lambda я использовал объект буфера для потребления тела.

Я пытался использовать Buffer(body, "utf8"), Buffer(body, "base64"), Buffer(body, "binary").

Это, в свою очередь, увеличивается до S3 для хранения с использованием putObject.

Проблема:

  • Файловый объект, который был установлен в S3, имеет либо размер файла 0, либо какое-то случайное значение, которое не соответствует исходному размеру файла.

  • Файл, загруженный с S3, открыть нельзя.

Неудачные подходы

Я рассмотрел multer и multiparty.Похоже, что это промежуточное программное обеспечение ExpressJS и ожидает ввода HttpRequest объект (это явно не упоминалось. Кажется, я достаточно невежественен, чтобы не предполагать, что они могут работать только с объектом HttpRequest, и мне потребовалосьпока выяснить).Я также недостаточно осведомлен, чтобы не знать, как преобразовать объект события AWS в объект HttpRequest.Но, тем не менее, кажется чрезмерным использовать движок Express только для управления загрузкой файлов.

Выставление моего S3 контейнера как public-read-write кажется довольно небезопасным.Таким образом, я не рассматриваю фронтенд, непосредственно перемещающий материал в / из моего ведра S3.

Мой запрос

Может кто-нибудь сказать мне, как заставить это работать?И / или альтернатива этому подходу?

1 Ответ

0 голосов
/ 22 сентября 2018

Это работает для меня:

Интерфейс

  • Специально кодирует File Объект в base64 строку.( Как преобразовать файл в base64 в JavaScript? )

  • Изучив закодированную строку-дату файла, вы обнаружите, что он имеет a ; заголовок с разделителями .Это также нигде явно не упоминается.Используйте .split() и .join(), чтобы удалить заголовок.

  • Теперь вы можете составить запрос в любой форме.Я выбрал легкий путь и использовал JSON.

  • Вот код, который делает то, что я упомянул:

    const getBase64fromFile = (file) => {
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => {
          console.log(`getBase64fromFile success.`);
          const spliced = reader.result.split(',');
          const header = spliced[0];
          spliced.shift();
          resolve({
            header: header,
            body: spliced.join('')
          });
        };
        reader.onerror = (err) => {
          console.log(`getBase64fromFile failed.`);
          reject(err);
        };
      });
    }
    
    uploadHandler() { 
      console.log(this.state.selectedFile);
    
    const selectedFile = this.state.selectedFile;
    const email = this.state.email;
    return getBase64fromFile(selectedFile)
    .then((base64Data) => {
      return {
        name: selectedFile.name,
        header: base64Data.header,
        base64: base64Data.body,
        email: email
      }
    })
    .then((body) => {
      console.log(`${JSON.stringify(body)}`);
      return body;
    })
    .then((body) => {
      this.setState({status: "Begin uploading..."});
      return fetch(this.state.url+"/upload",
      { // Your POST endpoint
        method: 'POST',
        headers: {
          "Authorization": "Bearer " + this.state.token,
          "x-api-key": this.state.apikey,
          "Accept": "application/json",
        }, 
        body: JSON.stringify(body)
      });
    })
    .then(
      response => response.json() // if the response is a JSON object
    )
    .then(
      success => {
        console.log(success); // Handle the success response object
        this.setState({
          status: success.message
        });
      }
    )
    .catch(
      error => {console.log(error) ;// Handle the error response object
        this.setState({
          status: JSON.stringify(error)
        });
      })
    ;
    }
    

(https://github.com/flameoftheforest/yaUserMan/blob/master/Tests/frontend/src/App.js)

AWS-Lambda

  • Теперь мы знаем, что данные поступают в виде строки base64, преобразуем их в октет, используя Buffer.from(body, "base64").

  • Вывод Buffer.from() - это <binary string>, который требуется putObject.

  • Вот код, который делает то, что я упомянул:

    const params = {
      Bucket: process.env.IMAGE_BUCKET,
      Key: uuid() + event.body.name,
      Body: Buffer.from(event.body.base64, 'base64'),
      ACL: "public-read"
    };
    

(https://github.com/flameoftheforest/yaUserMan/blob/master/yaUserMan/file2S3Helper.js)

Ссылка: https://medium.com/@olotintemitope/how-to-upload-files-to-amazon-s3-using-nodejs-lambda-and-api-gateway-bae665127907

...