Как отправить файл на aws s3 с помощью узла Js?

Итак, я новичок в стеке MERN и настроил форму для загрузки изображения и отправки его в свою корзину в aws s3. Я не получаю ответа. Я уверен, что в моем коде должна быть какая-то ошибка. Я не получаю ответа. Я следовал учебнику, но мой код не работает. Сервер.js

const express = require("express");
const aws = require("aws-sdk");
var cors = require("cors");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const app = express();
const items = require("./routes/api/items"); // Contains all the api routes

// for uploading the images
const fs = require("fs");
const fileType = require("file-type");
const bluebird = require("bluebird");
const multiparty = require("multiparty");

// Body Parser middleware
app.use(bodyParser.json());
app.use(cors());
// DB config
const db = require("./config/keys").mongoURI;

// config for access key and id
aws.config.update({
  region: "us-east-1",
  accessKeyId: process.env.AWSAccessKeyId,
  secretAccessKey: process.env.AWSSecretKey
});

const S3_BUCKET = process.env.bucket;
console.info(S3_BUCKET);

exports.sign_s3 = (req, res) => {
  const s3 = new aws.S3(); // Create a new instance of S3
  const fileName = req.body.fileName;
  const fileType = req.body.fileType;

  // Set up the payload of what we are sending to the S3 api
  const s3Params = {
    Bucket: S3_BUCKET,
    Key: fileName,
    Expires: 500,
    ContentType: fileType,
    ACL: "public-read"
  };

  // Make a request to the S3 API to get a signed URL which we can use to upload our file
  s3.getSignedUrl("putObject", s3Params, (err, data) => {
    if (err) {
      console.info(err);
      res.json({ success: false, error: err });
    }

    // Data payload of what we are sending back, the url of the signedRequest and a URL where we can access the content after its saved.

    const returnData = {
      signedRequest: data,
      url: `https://${S3_BUCKET}.s3.amazonaws.com/${fileName}`
    };
    // Send it all back

    res.json({ success: true, data: { returnData } });
  });
};

mongoose
  .connect(db, { useNewUrlParser: true })
  .then(() => console.info("Mongo is laoded"))
  .catch(err => console.info(err));

app.use("/api/items", items); // redirecting api routes to items

const port = process.env.PORT || 5000;

app.listen(port, () => console.info("Server started"));

Я сохранил свои учетные данные aws в файле .env в корневом каталоге. Остальные компоненты моей формы работают нормально. Только изображение не сохраняется в aws. Я попытаюсь абстрагировать код, чтобы удалить ненужные детали. Пользовательская форма.jsx

 handleSubmit = e => {
    e.preventDefault();
    let file = this.uploadInput.files[0];
    // Split the filename to get the name and type
    let fileParts = this.uploadInput.files[0].name.split(".");
    let fileName = fileParts[0];
    let fileType = fileParts[1];
    console.info("Preparing the upload");
    axios
      .post("http://localhost:5000/api/items", {
        fileName: fileName,
        fileType: fileType
      })
      .then(response => {
        var returnData = response.data.data.returnData;
        var signedRequest = returnData.signedRequest;
        var url = returnData.url;
        this.setState({ url: url });
        console.info("Recieved a signed request " + signedRequest);

        // Put the fileType in the headers for the upload
        var options = {
          headers: {
            "Content-Type": fileType
          }
        };
        axios
          .put(signedRequest, file, options)
          .then(result => {
            console.info("Response from s3");
            this.setState({ success: true });
          })
          .catch(error => {
            alert("ERROR " + JSON.stringify(error));
          });
      })
      .catch(error => {
        alert(JSON.stringify(error));
      });

    // update ends
    const users = {
      name: this.state.name,
      contact: this.state.contact,
      company: this.state.company,
      mail: this.state.mail,
      key: this.state.key,
      apps_no: this.state.apps_no
    };

    axios
      .post(
        "http://localhost:5000/api/items",
        {
          name: users.name,
          contact_no: users.contact,
          company_name: users.company,
          key: users.key,
          mail: users.mail,
          apps_no: users.apps_no
        },
        {
          headers: {
            "content-type": "application/json"
          }
        }
      )
      .then(res => {
        console.info("Post submitted with response " + res.status);
        console.info("Mail: " + users.mail);
      })
      .catch(function(error) {
        console.info(error);
      });

    this.props.history.push("/form-submitted");
  };

  componentDidMount() {
    axios.get("http://localhost:5000/api/items").then(resp => {
      console.info(resp.data);
    });
  }

В функции рендеринга я использую тег onClick в теге формы для отправки деталей. Поле ввода: <

center>
            <h1>UPLOAD A FILE</h1>
            {this.state.success ? <Success_message /> : null}
            <input
              onChange = {this.handleFileChange.bind(this)}
              ref = {ref => {
                this.uploadInput = ref;
              }}
              type = "file"
            />
            <br />

приставка:

Array(22)
UserForm.jsx:54 Preparing the upload
UserForm.jsx:115 Post submitted with response 200

В моем коде явно много ошибок. Помощь приветствуется. Редактировать: items.js-

const express = require("express");
const router = express.Router();

// Item model
const Item = require("../../models/Item");

// Routes
// @get API item get all items
// make a get req
router.get("/", (req, res) => {
  Item.find().then(items => res.json(items));
});

// @get Api item POST all items
// make a post req
// create an item
router.post("/", (req, res) => {
  const newItem = new Item({
    name: req.body.name,
    contact_no: req.body.contact_no,
    company_name: req.body.company_name,
    key: req.body.key,
    mail: req.body.mail,
    apps_no: req.body.apps_no
  });

  newItem.save().then(item => res.json(item));
});

// @del api item.
// delete request
router.delete("/:id", (req, res) => {
  Item.findById(req.params.id)
    .then(item => item.remove().then(() => res.json({ success: true })))
    .catch(err => res.status(404).json({ success: false }));
});

module.exports = router;

закомментируйте строку this.props.history.push("/form-submitted"); и повторите попытку.

hoangdv 29.05.2019 17:32

Пробовал.. Не работает.

Arjun Kashyap 29.05.2019 18:20

Предоставьте свой ./routes/api/items. Проверить sign_s3 функция была вызвана или нет.

hoangdv 30.05.2019 03:35

Я предоставил маршруты API. Я не думаю, что я вызвал функцию sign_s3.

Arjun Kashyap 30.05.2019 07:13
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
787
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вот что мы сделали:

Мы настроили AWS cli в нашей среде, проверьте эту ссылку: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html, в прямом эфире сделайте свой проект для настройки и чтения необходимых ключей AWS безопасным способом, но не храните никакие ключи в файле .env или в коде после того, как скрипт будет выглядеть так: :

const AWS = require('aws-sdk');
const s3 = new AWS.S3();

let putParams = {
            Body: fileCotent, 
            Bucket: s3BucketName, 
            Key: fileName,
            ContentType:'image/png'

        };
        s3.putObject(putParams, function(err, data) {
            if (err) console.info(err, err.stack); 
            else     console.info(data); 
            done();

        });
Ответ принят как подходящий

Вы получаете signedUrl по запросуPOST /api/items

axios
  .post("http://localhost:5000/api/items", {
    fileName: fileName,
    fileType: fileType
  })

но ваш маршрутизатор обрабатывает POST /api/items запрос на сохранение Item (вместо получения подписанного URL-адреса S3).

В вашем обработчике вы обрабатываете только случай успеха newItem.save().then(item => res.json(item));, затем, когда вы вызываете запрос с недопустимым телом (fileName, fileType), запрос никогда не отвечает в случае ошибки (это означает, что ваш клиент все еще ждет «вечно»)

Решение: создайте новый маршрутизатор, он будет обрабатывать запрос на получение подписанного URL-адреса.

  • Обновите клиентскую частьServer.js

    app.post('/signed-url', exports.sign_s3); // this line

    mongoose

    ...

  • Обновите клиентскую частьUserForm.jsx:

    console.info("Preparing the upload");

    axios

    .post("http://localhost:5000/signed-url") // instead of http://localhost:5000/api/items

Другие вопросы по теме