The upload plugin empowers your thorin application to handle file uploads. In order for it to work, your application must use a http transport. Behind the scenes, the plugin uses busboy to handle file uploading. You also must specify the store solution to use for uploads. We currently only offer the AWS S3 one.

Installation and usage
# install the upload plugin
npm i --save thorin-plugin-upload@1.x
# install the aws upload storage
npm i --save thorin-plugin-upload-aws@1.x
'use strict';
// app.js entry file
const thorin = require('thorin');
// Register the plugins

// Make the upload plugin use the upload-aws for storage.
thorin.on(thorin.EVENT.RUN, 'plugin.upload', (pluginObj) => {
   pluginObj.registerStorage('aws', thorin.config('aws'));
}); => {});

# update config/app.js with your configuration
Default configuration
  • transporthttpthe name of the http transport
  • limits.fieldNameSize120the maximum field name size in bytes
  • limits.fieldSize512000 the maximum field size.
  • limits.fileSize20 * 1000000the maximum file size, defaults to 20MB
  • limits.files1the maximum number of files allowed to be uploaded at once. We recommend only one.
  • limits.headerPairs120the maximum number of HTTP headers
Default storage configuration

The upload storage configuration for AWS should be placed under the aws config key in your application configuration.

  • keystringthe Amazon accessKeyId
  • secretstringthe Amazon secretAccessKey
  • signatureVersionv4the signature version to use
  • bucketstringthe bucket name to use
  • regionstringthe region name to use
'use strict';
// File: config/app.js
module.exports = {
   "plugin.upload": {
      "limits": {
         fileSize: 30 * 1000000  // make it 30MB
   "aws": {
      accessKeyId: 'YOUR_ACCESS_KEY_ID',
      secretAccessKey: 'YOUR_SECRET_ACCESS_KEY',
      bucket: 'YOUR_BUCKET',
      region: 'eu-central-1'
Plugin functionality
The FileUpload class used while uploading a file
The storage interface exposed by the plugin. If you want to work with your own storage solution, make sure to implement this interface.
pluginObj.addHandler(name, uploadPath)
Registers a new upload handler that works almost as a thorin.Action but with a few other functionalities. This will return a UploadHandler instance.
  • namestringthe name of the upload action.
  • uploadPathstringthe HTTP POST alias for the upload path
pluginObj.registerStorageClass(type, StorageClass)
Registers a new storage class that can then later be used as the storage solution of a file upload.
  • typestringthe type of the storage solution, eg. aws
  • StorageClassimplements pluginObj.IStoragethe storage class that implements the upload functionality
pluginObj.registerStorage(type, name, config)
Creates and caches an instance of the given storage class type. Ways of calling:
  • registerStorage(type, instanceName, config)
  • registerStorage(type, config)
  • registerStorage(storageInstanceObj)
Returns a previously registered storage instance by its name.
The UploadHandler class
  • pathstringthe upload path as the alias of the action
  • fieldNamestring, assetthe name of the form field that will contain the upload file
  • mimeTypesarray(string)an array of allowed file mimeTypes
  • extensionsarray(string)an array of allowed file extensions
  • limitsobjectaction-specific limits to apply to file uploads. See limits options above.
Adds the given mime type as an allowed mimeType
Manually set the field name that will contain the file (by default, asset)
handlerObj.limit(key, val)
Manually update the default limitations.
Set the default storage provider to use for the actual file uploading.
  • storage(storageInstanceName=string)
  • storage(fn) => storageInstanceName = fn(intentObj, fileObj)
  • storage(fn) => storageInstanceObj = fn(intentObj, fileObj);
Registers the callback function that will be called when a file is being processed by busboy. The handler will be called with fn(fileObj, next)
The FileUpload class
  • namestringthe name of the file that will be uploaded
  • sizenumberthe size of the file that is being uploaded. It is set once the upload is complete.
  • mimeTypestringthe mimeType of the file.
  • encodingstringthe file encoding
  • keystring, randomthe unique upload key that will be used as the file's key
  • folderstringthe name of the folder that the file will be placed in.
  • optionsobjectadditional storage-specific options.
Returns the ReadableStream of the incoming file upload
Returns the JSON representation of the file. Default object contains url, size properties.
Marks the file as being too large and stops its processing.
Sets the folder hierarchy of the file.
Sets additional options that will be read by the storage class.
Constructs the entire file key, used by the storage class.
The pluginObj.IStorage storage interface

This is the storage interface that has to be implemented for custom storage options.

save(fileObj, opt) : Promise
This will be called with a UploadFile object, that contains a stream. It is supposed to return a promise that will attach the full URL to the UploadFile instance and the file size if possible.
canRemove(fileUrl) : Boolean
This will check if the current storage option was saved to store the given file. For example. would return true for storages that use my-bucket and false otherwise.
remove(fileUrl) : Promise
This will remove the actual fileUrl from the server, returning a promise.
Full example handler
'use strict';

const uploadObj = thorin.plugin('upload'),
  logger = thorin.logger('upload');

  .addHandler('upload.image', '/upload/image')   // the POST /upload/image alias
  .template('session.account')   // inherit authorization from a session.account action template
  .enableCors()                  // enable CORS for the file uploading
  .limit('fileSize', '2mb')      // limit to 2MB
  .mimeType('image/*')           // accept only images
  .extension('jpg', 'jpeg', 'png')  // of type jpeg and png
  .storage('aws')                   // use the AWS storage class
  .upload((intentObj, fileObj, next) => {
    const account = intentObj.session.account;
    fileObj.setFolder(`account/${}`); // change the folder of the image
  .use((intentObj) => {
    const fileObj ='file');
    intentObj.result(fileObj).send();  // return the url of the file.
    logger.trace('Uploaded image for account ' +;
  // The final URL of the image would be

Do you have a question or is something missing?

You can always create a new issue on GitHub or contact one of the core founders by chat.