0

I am trying to create an item where users will be able to upload a file image, that uploads the file to amazon s3, and returns a string for the image address that should be passed into mongoDB as a single document along with text inputs such as name of item, description, dates etc.

So far I have created a simple mongoDB model with a name and an image to test uploading a file with one text input, but when I try to test it in postman using form-urlencoded, there is no option to select a file, and if i try to test it in form-data, I get an empty string for the name input, but my code does read the file and return a string for the file, just not both together.

My code is: setup file for amazon s3

const multer = require("multer");
const multerS3 = require("multer-s3");

const { secret_key, access_key, bucket_name } = require("../config/config");

aws.config.update({
    secretAccessKey: secret_key,
    accessKeyId: access_key,
    region: "us-east-2"
});

const s3 = new aws.S3();

const fileFilter = (req, file, cb) => {
    if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") {
        cb(null, true);
    } else {
        cb(new Error("Invalid Mime Type, only JPEG or PNG"), false);
    }
};

const upload = multer({
    fileFilter: fileFilter,
    storage: multerS3({
        s3: s3,
        bucket: bucket_name,
        acl: "public-read",
        metadata: function(req, file, cb) {
            cb(null, { fieldName: file.fieldname });
        },
        key: function(req, file, cb) {
            cb(null, Date.now().toString());
        }
    })
});

module.exports = upload;

controller file for the upload at the target route

const upload = require("../services/file-upload");
const singleUpload = upload.single("img");

let uploadArtefact = (req, res) => {
    const { name } = req.body;
    singleUpload(req, res, err => {
        if (err) {
            return res.status(422).send({
                errors: [{ title: "File Upload Error", detail: err.message }]
            });
        }

        let artefact = new Artefact({
            name: name,
            img: req.file.location
        });

        if (!name) {
            return res.json({
                success: false,
                error: "Invalid Inputs"
            });
        }
        artefact.save(err => {
            if (err) {
                return res.json({ sucess: false, error: err });
            }
            return res.json({ success: true });
        });
    });
};

module.exports = uploadArtefact;

So I was wondering what would be the best approach to this? Is there a way to submit files with text in one request? I would preferably want to be able to find a way to send them both together.

  • Your question broadly covers mongodb, S3, and an upload/GUI framework. When you say "submit files with text in one request" what do you mean, exactly? Your overall approach is a good one: put the image in S3, grab the handle to it, and store the handle plus metadata and other data in a doc in MongoDB. – Buzz Moschetti Oct 05 '19 at 16:41
  • Basically my problem is that when I'm using postman to test it using form-data, my code: const { name } = req.body returns nothing, but I get my image fine. If i test it with form-urlencoded, I get the name fine, but it doesn't let me input files, so I don't know how to get it so that when I do const { name } = req.body, so that I will actually receive the name – Andrew Zhang Oct 06 '19 at 03:15

1 Answers1

0

Nevermind, I realised that multer can parse the text but i just needed to put the const { name } = req.body; inside the singleUpload{} section.