【发布时间】:2020-12-09 22:39:26
【问题描述】:
我想使用 formidable 和 knox 将文件上传到 AWS S3 存储桶,但我每次都得到 400 并且文件没有上传。我的代码类似于:nodejs knox put to s3 results in a 403,唯一的区别是我的 readFile 的第一个参数来自我的 windows 临时文件夹,我通过确保我的存储桶名称只是小写字母来尝试评论中的解决方案但这也没有工作。可以的话请帮忙,谢谢。我的代码如下:
App.js
const express = require("express"),
path = require("path"),
config = require("./config"),
knox = require("knox"),
fs = require("fs"),
os = require("os"),
formidable = require("formidable"),
gm = require("gm"),
mongoose = require("mongoose");
mongoose.connect(config.dbURL, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const app = express();
app.set("views", path.join(__dirname, "views"));
app.engine("html", require("hogan-express"));
app.set("view engine", "html");
app.use(express.static(path.join(__dirname, "public")));
app.set("port", process.env.PORT || 3000);
app.set("host", config.host);
let knoxClient = knox.createClient({
key: config.S3AccessKey,
secret: config.S3Secret,
bucket: config.S3Bucket,
});
const server = require("http").createServer(app);
const io = require("socket.io")(server);
require("./routers")(
express,
app,
formidable,
fs,
os,
gm,
knoxClient,
mongoose,
io
);
server.listen(app.get("port"), function () {
console.log("PhotoGRID Running on port: " + app.get("port"));
});
路由器(index.js)
module.exports = (
express,
app,
formidable,
fs,
os,
gm,
knoxClient,
mongoose,
io
) => {
//os.tmpDir = os.tmpdir;
let Socket;
io.on("connection", function (socket) {
Socket = socket;
});
const singleImage = new mongoose.Schema({
filename: {
type: String,
require: true,
},
votes: {
type: Number,
require: true,
},
});
let singleImageModel = mongoose.model("singleImage", singleImage);
let router = express.Router();
router.get("/", function (req, res, next) {
res.render("index", { host: app.get("host") });
});
router.post("/upload", function (req, res, next) {
// File upload
function generateFilename(filename) {
let ext_regex = /(?:\.([^.]+))?$/;
let ext = ext_regex.exec(filename)[1];
let date = new Date().getTime();
let charBank = "abcdefghijklmnopqrstuvwxyz";
let fstring = "";
for (let i = 0; i < 15; i++) {
fstring += charBank[parseInt(Math.random() * 26)];
}
return (fstring += date + "." + ext);
}
let tmpFile, nFile, fName;
let newForm = new formidable.IncomingForm();
newForm.keepExtensions = true;
newForm.parse(req, function (err, fields, files) {
tmpFile = files.upload.path;
fName = generateFilename(files.upload.name);
nFile = os.tmpDir() + "/" + fName;
res.writeHead(200, { "Content-type": "text/plain" });
res.end();
});
newForm.on("end", function () {
fs.rename(tmpFile, nFile, function () {
// Resize the image and upload this file into the S3 bucket
gm(nFile)
.resize(300)
.write(nFile, function () {
// Upload to the S3 Bucket
fs.readFile(nFile, function (err, buf) {
let req = knoxClient.put(fName, {
"Content-Length": buf.length,
"Content-Type": "image/jpg",
});
req.on("response", function (res) {
if (res.statusCode == 200) {
//This means that the file is in the S3 Bucket
console.log(fName + " is in the S3 bucket");
let newImage = new singleImageModel({
filename: fName,
votes: 0,
}).save();
Socket.emit("status", { msg: "Saved!!", delay: 3000 });
Socket.emit("doUpdate", {});
// Delete the Local file
fs.unlink(nFile, function () {
console.log("Local file deleted!");
});
} else {
console.log(
err +
fName +
" did not get to the database or S3 bucket so " +
nFile +
" was not deleted " +
res.statusCode
);
}
});
req.end(buf);
});
});
});
});
});
app.use("/", router);
};
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>PhotoGrid</title>
<link rel="stylesheet" href="../css/main.css" />
<script src="http://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="../js/photogrid_utils.js"></script>
<script>
$(function () {
let host = "{{host}}";
$(document).on("click", "#doUpload", function () {
uploadNow();
});
let socket = io(host);
socket.on("status", function (data) {
showStatus(data.msg, data.delay);
});
socket.on("doUpdate", function () {
renderList();
});
function uploadNow() {
let uploadURL = host + "/upload";
let uploadFile = $(".uploadPic");
if (uploadFile.val() != "") {
let form = new FormData();
form.append("upload", uploadFile[0].files[0]);
// Perform the AJAX POST request and send the file
ajax({
method: "post",
url: uploadURL,
success: function () {
$(".progress").fadeOut(200);
uploadFile.val("");
},
progress: function (e) {
if (e.lengthComputable) {
let perc = Math.round((e.loaded * 100) / e.total);
$(".progress").css("width", perc + "%");
}
},
payload: form,
});
}
}
});
</script>
</head>
<body>
<div class="container">
<div class="topDeck">
<div class="logo">
<a href="{{host}}">
<h1>PhotoGRID</h1>
</a>
</div>
<div class="controls">
<input type="file" name="uploadPic" class="uploadPic" />
<button id="doUpload">Upload</button>
<div class="progressBarDiv">
<div class="progress"></div>
</div>
<h5 class="status"></h5>
</div>
</div>
<div class="gallery">
<ul>
<!-- Repeat the following <li> structure for every image -->
<li>
<div class="overlay">
<div class="voteCtrl">
<a href="#" class="voteUp">
<img
src="../images/voteup.png"
alt="Click Here to Vote Up !"
/>
<h4>100</h4>
</a>
</div>
</div>
<div class="imageHolder">
<img src="../images/someimage.jpg" alt="" />
</div>
</li>
<!-- End Repeat -->
</ul>
</div>
</div>
</body>
</html>
【问题讨论】:
-
调整您当前的实施/方案与此处列出的可能原因:aws.amazon.com/premiumsupport/knowledge-center/…
-
@xandercoded 我已经经历了所有可能的原因,我认为我的问题不是由任何原因引起的。你能想到我的文件没有上传的其他原因吗?
-
可能由于各种原因而失败。什么是响应消息?将
400响应代码(或403)与此处列出的docs.aws.amazon.com/AmazonS3/latest/API/… 进行比较。 -
@xandercoded 我打开了链接,看到了这么多 400 个带有错误名称的状态代码。我写到控制台的只是状态码,我真的不知道如何将错误名称写入控制台。如果可以的话,它可能会帮助我知道我正在处理的确切 400 错误
标签: node.js mongodb express amazon-s3 formidable