docs/advanced_topics/documents/storing_and_serving.md
(storing_and_serving)=
Wagtail follows Django’s conventions for managing uploaded files. For configuration of FileSystemStorage and more information on handling user uploaded files, see .
Wagtail uses the STORAGES["default"] setting to determine where and how user-uploaded files are stored. By default, Wagtail stores files in the local filesystem.
Document serving is controlled by the WAGTAILDOCS_SERVE_METHOD method. It provides a number of serving methods which trade some of the strictness of the permission check that occurs when normally handling a document request for performance.
The serving methods provided are direct, redirect and serve_view. When WAGTAILDOCS_SERVE_METHOD is unspecified or set to None, Wagtail picks the default based on the active storage backend: serve_view for local storage, and redirect for remote storage backends that expose a URL but not a local filesystem path. For example:
WAGTAILDOCS_SERVE_METHOD = "redirect"
(documents_security_considerations)=
Any system that allows user-uploaded files is a potential security risk.
When using FileSystemStorage, documents are stored in a documents subdirectory within your site's MEDIA_ROOT. In this case, WAGTAILDOCS_SERVE_METHOD defaults to serve_view, where Wagtail serves the document through a Django view that enforces privacy checks.
When using the serve_view method:
documents subdirectory of MEDIA_ROOT within your web server configuration. This prevents users from bypassing collection privacy settings by accessing documents at their direct URL.The alternative serve methods 'direct' and 'redirect' work by serving the documents directly from MEDIA_ROOT. This means it is not possible to block direct access to the documents subdirectory, and so users may bypass permission checks by accessing the direct URL. Also, in the case that users with access to the Wagtail admin are not fully trusted, you will need to take additional steps to prevent common issues such as execution of scripts in documents:
Content-Security-Policy: default-src 'none' header for files within the documents subdirectory, which will prevent the execution of scripts in those files.Content-Disposition: attachment header for files within the documents subdirectory, which will force the browser to download the file rather than displaying it inline.If a remote ("cloud") storage backend is used, the serve method will default to 'redirect' and the document will be served directly from the cloud storage file url. In this case (as with 'direct'), Wagtail has less control over how the file is served and users may be able to bypass permission checks, and scripts within documents may be executed (depending on the cloud storage service's configuration). However, whilst cross-site scripts attacks are still possible, the impact is reduced as the document is usually served from a different domain to the main site.
If these limitations are not acceptable, you may set the WAGTAILDOCS_SERVE_METHOD to serve_view and ensure that the documents are not publicly accessible using the cloud service's file url.
The steps required to set headers for specific responses will vary, depending on how your Wagtail application is deployed and which storage backend is used. For the serve_view method, a Content-Security-Policy header is automatically set for you (unless disabled via ) to prevent the execution of scripts embedded in documents.
Wagtail provides the WAGTAILDOCS_CONTENT_TYPES setting to specify which document content types are allowed to be uploaded. For example:
WAGTAILDOCS_CONTENT_TYPES = {
'pdf': 'application/pdf',
'txt': 'text/plain',
}
Inline content types can be specified using WAGTAILDOCS_INLINE_CONTENT_TYPES, are displayed within the rich text editor.
For example:
WAGTAILDOCS_INLINE_CONTENT_TYPES = ['application/pdf', 'text/plain']
Wagtail allows you to specify the permitted file extensions for document uploads using the WAGTAILDOCS_EXTENSIONS setting.
It also validates the extensions using Django's {class}~django.core.validators.FileExtensionValidator. For example:
WAGTAILDOCS_EXTENSIONS = ['pdf', 'docx']
Use the WAGTAILDOCS_MAX_UPLOAD_SIZE setting to limit how large uploaded documents can be (in bytes). This helps protect against denial-of-service from oversized uploads. For example:
WAGTAILDOCS_MAX_UPLOAD_SIZE = 10 * 1024 * 1024 # 10MB
If unset, Wagtail allows any file size (subject to Django's DATA_UPLOAD_MAX_MEMORY_SIZE and FILE_UPLOAD_MAX_MEMORY_SIZE, and any limits enforced by your web server or storage backend).
The `WAGTAILDOCS_MAX_UPLOAD_SIZE` setting was added.
(document_antivirus_scanning)=
Wagtail does not perform anti-virus (AV) scanning on uploaded documents. For sites with a need for this kind of validation of Wagtail files, two common patterns are:
WAGTAILDOCS_DOCUMENT_FORM_BASE and calling out to a scanner. Returning a ValidationError will surface the message to the editor.For most sites, storage-side scanning is the lowest-risk option as it does not block uploads on the scanner being available, and naturally extends to files written outside of Wagtail (for example by background tasks or other applications writing to the same object storage).
Wagtail provides the WAGTAILDOCS_PASSWORD_REQUIRED_TEMPLATE setting to use a custom template when a password is required to access a protected document. Read more about .
Here's an example:
WAGTAILDOCS_PASSWORD_REQUIRED_TEMPLATE = 'myapp/document_password_required.html'