Итак, я новичок в стеке 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;
Пробовал.. Не работает.
Предоставьте свой ./routes/api/items
. Проверить sign_s3
функция была вызвана или нет.
Я предоставил маршруты API. Я не думаю, что я вызвал функцию sign_s3.
Вот что мы сделали:
Мы настроили 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
закомментируйте строку
this.props.history.push("/form-submitted");
и повторите попытку.