NodeJS Knox Formidable 结果为 400,文件未上传到 S3 存储桶

NodeJS Knox Formidable results in a 400, File not Uploaded to S3 Bucket

我想使用 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>

我无法让我的代码与 knox 一起工作,我一直收到 400 statusCode,而且我的文件没有上传到 S3。所以我使用了 aws-sdk 并且它像魔术一样工作。我的文件正在上传并保存到我的 mongo 数据库中。对于那些可能遇到同样问题的人,这就是我所做的:

const { config } = require("aws-sdk");

module.exports = (express, app, formidable, fs, os, gm, s3, 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": "image/JPG" });
      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",
                "x-amz-acl": "public-read",
              }); */

            const fileContent = fs.readFileSync(nFile);

            const params = {
              Bucket: require("../config").S3Bucket,
              Key: fName,
              Body: fileContent,
            };

            s3.upload(params, function (err, data) {
              // Delete the Local file
              fs.unlink(nFile, function (err) {
                console.log("Local file deleted!");
                if (err) {
                  console.error(err);
                }
              });
              console.log("PRINT FILE: ", fName);
              if (err) {
                console.log("ERROR MSG: ", err);
                res.status(500).send(err);
              } else {
                //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", {});

                res.status(200).end();
              }
            });

            /*               req.on("response", function (res) {
                if (res.statusCode == 200) {
                  

                } else {
                  console.log(
                    err +
                      fName +
                      " did not get to the database or S3 bucket so " +
                      nFile +
                      " was not deleted " +
                      res.statusCode
                  );
                  console.log(res.statusMessage);
                }
              }); */

            // req.end(buf);
            //     });
          });
      });
    });
  });

  app.use("/", router);
};