1

My application has a web form where users can upload multiple image files. I want the location of the files (hosted on AWS S3) to be stored in an array that I have as part of the model called userPhotos. The file locations are stored in req.files, and I can access them in req.files.location, and place them together in an array using a for-loop, just as I did below. However, now, before creating a new document, I want fileInfo array to be included in req.body.userPhotos.

How can I achieve this?

exports.createOne = (Model) =>
  catchAsync(async (req, res, next) => {
    if (req.files.length > 0) {
      const fileInfo = [];
      for (i = 0; i < req.files.length; i++) {
        fileInfo.push(req.files[i].location);
      }
      console.log(fileInfo);
    }

    const doc = await Model.create(req.body);
    res.status(201).json({
      status: 'success',
      data: {
        data: doc,
      },
    });
  });
Chris Clark
  • 488
  • 2
  • 19

2 Answers2

1

I think what you want is “res.locals”.

res.locals.userPhotos = fileInfo

Express built this functionality into the response object, because it assumes you will send this array to the front-end at some point.

You don’t need to send it to the front, you can continue to use locals on the back-end, treating it as an object:

You can append as many things as you want to res.locals.

If I missed something or if this doesn’t answer your question, please comment!

Izzi
  • 2,184
  • 1
  • 16
  • 26
0

Yes, it is possible, but...

Usually you would not just use req.body directly with your database because the client could put things into that object that you don't really want in your database. Remember, a POST coming in from a client can have anything in it - it is not just limited to what you want to be in that object.

So, the safer way to do so would be to create your own object and copy over only the properties that you specifically want. That can be done either manually or you can make a little function that you pass an array of property names to that will copy all those over. And, then after copying over the desired properties, you can then add additional properties if you want before saving it in the database.

If you really wanted to add more things to req.body, it is just a plain Javascript object so you can just directly assign new properties to it.

FYI, here's a safeCopy function that makes a copy of a list of properties into a new object:

function safeCopy(srcObj, props, destObj = {}) {
    for (let prop of props) {
        if (srcObj.hasOwnProperty(prop)) {
            destObj[prop] = srcObj[prop];
        }
    }
    return destObj;
}

// sample req.body that has unplanned properties on it
const req = {body: {
    fname: "Jack",
    lname: "Bundy",
    age: 31,
    girlfriend: "Alice",    // undesired property
    salary: 1000000         // undesired property
}};

// make copy that only has desired properties
let newObj = safeCopy(req.body, ["fname", "lname", "age"]);
// see new object with only the desired properties
console.log(newObj);

For a way to do this with ES6 object destructuring assignment, see How to get a subset of a javascript object's properties. While cool to see the extent of what you can do with advanced destructuring assignment, I don't always find it's tricks all that readable and clear which is always a priority for me. Three years from now when I've long forgotten this code, I want to be able to easily recognize what the code does. Anyway, that's another way to make a copy of a set of properties from the object.

jfriend00
  • 683,504
  • 96
  • 985
  • 979