Search code examples
apostrophe-cmsapostrophe

How do I set additional file groups in Apostrophe 3 CMS attachment module?


File groups in the Apostrophe 3 CMS attachment module specify which files can be uploaded in a file upload form. By default, Apostrophe 3 offers two file groups: office and image.

I would like to add two more file groups: pdf (only) and zip (for archives). As suggested in Custom File Groups :

Developers can configure file type groups in addition to office and image using the fileGroups option of the @apostrophecms/attachment module.

Unfortunately there is no example on how to do that, so I referred to the Apostrophe 2 documentation fileGroups. This documentation mentions the default configuration:

[
  {
    name: 'images',
    label: 'Images',
    extensions: [ 'gif', 'jpg', 'png' ],
    extensionMaps: {
      jpeg: 'jpg'
    },
    // uploadfs should treat this as an image and create scaled versions
    image: true
  },
  {
    name: 'office',
    label: 'Office',
    extensions: [ 'txt', 'rtf', 'pdf', 'xls', 'ppt', 'doc', 'pptx', 'sldx', 'ppsx', 'potx', 'xlsx', 'xltx', 'csv', 'docx', 'dotx' ],
    extensionMaps: {},
    // uploadfs should just accept this file as-is
    image: false
  }
]

I extended the configuration and added it to the @apostrophecms/attachment module:

// modules/@apostrophecms/attachment/index.js
module.exports = {
  options: {
    '@apostrophecms/attachment': {
      options: {
        fileGroups: [
          {
            name: 'pdf',
            label: 'PDF',
            extensions: ['pdf'],
            extensionMaps: {},
            // uploadfs should just accept this file as-is
            image: false
          },
          {
            name: 'zip',
            label: 'ZIP',
            extensions: ['zip'],
            extensionMaps: {},
            // uploadfs should just accept this file as-is
            image: false
          },
          {
            name: 'image',
            label: 'Image',
            extensions: ['gif', 'jpg', 'png', 'svg', 'txt', 'rtf', 'pdf', 'xls', 'ppt', 'doc', 'pptx', 'sldx', 'ppsx', 'potx', 'xlsx', 'xltx', 'csv', 'docx', 'dotx', 'jpeg'],
            extensionMaps: {
              jpeg: 'jpg'
            },
            // uploadfs should treat this as an image and create scaled versions
            image: true
          },
          {
            name: 'office',
            label: 'Office',
            extensions: [ 'txt', 'rtf', 'pdf', 'xls', 'ppt', 'doc', 'pptx', 'sldx', 'ppsx', 'potx', 'xlsx', 'xltx', 'csv', 'docx', 'dotx' ],
            extensionMaps: {},
            // uploadfs should just accept this file as-is
            image: false
          }
        ]
      }
    }
  }
};

In a widget, I configured a field to only allow zip files:

file: {
  label: 'File',
  type: 'attachment',
  fileGroup: 'zip'
}

When uploading a valid "Archive.zip" file, I am presented with this error message:

" File type was not accepted. Allowed extensions: "

Error dialogue screenshot

How do I configure custom file groups correctly for Apostrophe 3?


Solution

  • This is a limitation that we know about in a3. The way the attachment module is configured doesn't extend the fileGroups through the modules/@apostrophe/attachment/index.js file. Instead, you have to do it "manually" in that same file. So in your case it would be something like:

    module.exports = {
      init(self) {
        const newGroups = [
          {
            name: 'pdf',
            label: 'PDF',
            extensions: ['pdf'],
            extensionMaps: {},
            // uploadfs should just accept this file as-is
            image: false
          },
          {
            name: 'zip',
            label: 'ZIP',
            extensions: ['zip'],
            extensionMaps: {},
            // uploadfs should just accept this file as-is
            image: false
          }
        ];
        self.fileGroups = [ ...self.fileGroups, ...newGroups ];
      }
    };
    

    You can use this same type of pattern to extend the existing groups.

    ...
        const group = self.fileGroups.find((group) => group.name === 'office');
        group.extensions = [ ...group.extensions, 'woff2' ];
    ...
    

    Hope this solves it for you!