mirror of
https://github.com/directus/directus.git
synced 2026-01-22 20:47:54 -05:00
Add env var for max file upload size (#18735)
* Add limit to file size * Delete temp db record on file upload failure * Emit empty value on upload failure * Rename assets->files * Update reference * Finalize rename * Add changeset * Add proper exception
This commit is contained in:
5
.changeset/red-snails-tap.md
Normal file
5
.changeset/red-snails-tap.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@directus/api': minor
|
||||
---
|
||||
|
||||
Added a new `FILES_MAX_UPLOAD_SIZE` environment variable for setting a max value system-wide
|
||||
@@ -1,11 +1,13 @@
|
||||
import formatTitle from '@directus/format-title';
|
||||
import { toArray } from '@directus/utils';
|
||||
import Busboy from 'busboy';
|
||||
import bytes from 'bytes';
|
||||
import type { RequestHandler } from 'express';
|
||||
import express from 'express';
|
||||
import Joi from 'joi';
|
||||
import path from 'path';
|
||||
import env from '../env.js';
|
||||
import { ContentTooLargeException } from '../exceptions/content-too-large.js';
|
||||
import { ForbiddenException, InvalidPayloadException } from '../exceptions/index.js';
|
||||
import { respond } from '../middleware/respond.js';
|
||||
import useCollection from '../middleware/use-collection.js';
|
||||
@@ -34,7 +36,14 @@ export const multipartHandler: RequestHandler = (req, res, next) => {
|
||||
};
|
||||
}
|
||||
|
||||
const busboy = Busboy({ headers, defParamCharset: 'utf8' });
|
||||
const busboy = Busboy({
|
||||
headers,
|
||||
defParamCharset: 'utf8',
|
||||
limits: {
|
||||
fileSize: env['FILES_MAX_UPLOAD_SIZE'] ? bytes(env['FILES_MAX_UPLOAD_SIZE'] as string) : undefined,
|
||||
},
|
||||
});
|
||||
|
||||
const savedFiles: PrimaryKey[] = [];
|
||||
const service = new FilesService({ accountability: req.accountability, schema: req.schema });
|
||||
|
||||
@@ -88,6 +97,12 @@ export const multipartHandler: RequestHandler = (req, res, next) => {
|
||||
// Clear the payload for the next to-be-uploaded file
|
||||
payload = {};
|
||||
|
||||
fileStream.on('limit', () => {
|
||||
const error = new ContentTooLargeException(`Uploaded file is too large`);
|
||||
fileStream.emit('error', error);
|
||||
next(error);
|
||||
});
|
||||
|
||||
try {
|
||||
const primaryKey = await service.uploadOne(fileStream, payloadWithRequiredFields, existingPrimaryKey);
|
||||
savedFiles.push(primaryKey);
|
||||
|
||||
@@ -107,6 +107,10 @@ const allowedEnvironmentVars = [
|
||||
'STORAGE_.+_HEALTHCHECK_THRESHOLD',
|
||||
// metadata
|
||||
'FILE_METADATA_ALLOW_LIST',
|
||||
|
||||
// files
|
||||
'FILES_MAX_UPLOAD_SIZE',
|
||||
|
||||
// assets
|
||||
'ASSETS_CACHE_TTL',
|
||||
'ASSETS_TRANSFORM_MAX_CONCURRENT',
|
||||
|
||||
7
api/src/exceptions/content-too-large.ts
Normal file
7
api/src/exceptions/content-too-large.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { BaseException } from '@directus/exceptions';
|
||||
|
||||
export class ContentTooLargeException extends BaseException {
|
||||
constructor(message: string) {
|
||||
super(message, 413, 'CONTENT_TOO_LARGE');
|
||||
}
|
||||
}
|
||||
@@ -87,6 +87,9 @@ export class FilesService extends ItemsService {
|
||||
} catch (err: any) {
|
||||
logger.warn(`Couldn't save file ${payload.filename_disk}`);
|
||||
logger.warn(err);
|
||||
|
||||
await this.deleteOne(primaryKey);
|
||||
|
||||
throw new ServiceUnavailableException(`Couldn't save file ${payload.filename_disk}`, { service: 'files' });
|
||||
}
|
||||
|
||||
|
||||
@@ -197,6 +197,7 @@ function useUpload() {
|
||||
}
|
||||
} catch (err: any) {
|
||||
unexpectedError(err);
|
||||
emit('input', null);
|
||||
} finally {
|
||||
uploading.value = false;
|
||||
done.value = 0;
|
||||
|
||||
@@ -626,6 +626,7 @@ errors:
|
||||
RANGE_NOT_SATISFIABLE: Invalid range
|
||||
METHOD_NOT_ALLOWED: Method not allowed
|
||||
REQUESTS_EXCEEDED: Requests limit reached
|
||||
CONTENT_TOO_LARGE: Submitted item/file is too large
|
||||
security: Security
|
||||
value_hashed: Value Securely Hashed
|
||||
bookmark_name: Bookmark name...
|
||||
|
||||
@@ -680,6 +680,12 @@ purposes, collection of additional metadata must be configured:
|
||||
|
||||
<sup>[1]</sup>: Extracting all metadata might cause memory issues when the file has an unusually large set of metadata
|
||||
|
||||
### Upload Limits
|
||||
|
||||
| Variable | Description | Default Value |
|
||||
| ----------------------- | ------------------------------------------------------------------- | ------------- |
|
||||
| `FILES_MAX_UPLOAD_SIZE` | Maximum file upload size allowed. For example `10mb`, `1gb`, `10kb` | |
|
||||
|
||||
## Assets
|
||||
|
||||
| Variable | Description | Default Value |
|
||||
|
||||
Reference in New Issue
Block a user