Если ваш опыт загрузки файлов в S3 похож на мой, вы столкнетесь с огромным количеством информации, лишенной краткого, легко усваиваемого кода. Итак, я составил пошаговое руководство, которое перенесет вас из браузера на S3 с помощью Koa и FormData. Давайте начнем.

Обратите внимание, что это руководство будет работать для любой службы, совместимой с S3. Это означает, что, например, если вы используете DigitalOcean Spaces, код применим и к вам.

Во-первых, мы настроим наш сервер Koa для отправки файлов на S3. Это предполагает, что у вас уже есть настройка проекта узла.

  1. Установить библиотеки:
yarn add koa koa-router koa-body aws-sdk
// or
npm i koa koa-router koa-body aws-sdk

2. Напишите POST маршрут для обработки загрузок:

const Koa = require("koa");
const koaRouter = require("koa-router");
const koaBody = require("koa-body");
const router = new koaRouter();
router.post("/upload", async ctx => {
  const file = ctx.request.files.file;
  const { key, url } = await uploadFile({
    fileName: file.name,
    filePath: file.path,
    fileType: file.type,
  });
  ctx.body = { key, url };
});
// We enable multipart body parsing
app.use(koaBody({ multipart: true }));
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(process.env.PORT);

3. Реализуйте метод uploadFile:

const aws = require("aws-sdk");
const fs = require("fs");

const uploadFile = async ({ fileName, filePath, fileType }) => {
  return new Promise((resolve, reject) => {
    aws.config.update({
      region: "nyc3",
      // You'll need your service's access keys here
      accessKeyId: "",
      secretAccessKey: "",
    });

    const s3 = new aws.S3({
      apiVersion: "2006-03-01",
      // If you want to specify a different endpoint, such as using DigitalOcean spaces
      // endpoint: new aws.Endpoint("nyc3.digitaloceanspaces.com"),
    });

    const stream = fs.createReadStream(filePath);
    stream.on("error", function(err) {
      reject(err);
    });

    s3.upload(
      {
        ACL: "public-read",
        // You'll input your bucket name here
        Bucket: "bucket-name",
        Body: stream,
        Key: fileName,
        ContentType: fileType,
      },
      function(err, data) {
        if (err) {
          reject(err);
        } else if (data) {
          resolve({ key: data.Key, url: data.Location });
        }
      }
    );
  });
};

module.exports = { uploadFile };

Наконец, мы реализуем браузерную часть.

  1. Разместите <input type="file" /> на своей странице.
  2. Напишите обработчик onchange, который отправляет файл на ваш сервер:
// Select your file input
const fileInput = document.querySelector("input[type='file']");
// Add your onchange handler
imageUpload.onchange = async e => {
  const files = e.target.files;
  const fileToUpload = files[0];

  let data = new FormData();
  data.append("file", fileToUpload);

  // Send as multipart/form-data
  // Ensure the URL points to your server
  const response = await fetch("/upload", {
    method: "POST",
    body: data,
  });
  const { url } = await response.json();
  
  // Now you have a URL of the file uploaded to S3
};

Вот и все! В конце концов, вам нужно будет убедиться, что вы обрабатываете ошибки в процессе загрузки и проверяете ограничения файлов.

Я надеюсь, что это поможет другим, пытающимся найти простой пример загрузки файлов из браузера на сервер.