Search code examples
node.jsmongoosecloudinarykeystonejs

KeystoneJS CloudinaryImage upload via API


There seems to be lack of documentation on this topic. I'm trying to upload an image and set it to avatar: { type: Types.CloudinaryImage } in my Keystone model.

I'm posting content as multipart form data with the following structure: avatar: <raw_data>. Here is how I handle this in my API:

exports.upload_avatar = function(req, res) {
    if (!req.files.avatar) {
        console.info('Request body missing');
        return res.status(400).json({ message: 'Request body missing', code: 20 });
    }
    req.current_user.avatar = req.files.avatar;
    req.current_user.save();
} 

where current_user is a mongoose model. What I find confusing is how to set my CloudinaryImage type field to the data I receive in the API.


Solution

  • Ok after some digging through the source code, I figured out a way to do that:

    exports.upload_avatar = function(req, res) {
        req.current_user.getUpdateHandler(req).process(req.files, {fields: 'avatar'}, function(err) {
          if (err) {
              return res.status(500).json({ message: err.message || '', code: 10 });
          }
          res.send('');
        });
    }
    

    I had the following gotchas:

    • use getUpdateHandler to update CloudinaryImage field.
    • use "magic" naming for multipart form data fields you POST to your API: {field_name}_upload, which in my case would be avatar_upload.
    • process req.files, which is a dictionary with your field names as keys and your file data as values. req.body is empty due to some post-processing with multer.
    • invoke update handler on your keystone model (you need to fetch it with find first) rather than on a specific field. Then specify {fields: <>} to limit its scope, otherwise you could have some issues like validation errors trying to update the whole object.