Even though Zope with ZODB blobs is capable of handling big file uploads, its performance is weak in comparison to Nginx upload module.
Using the latter has many advantages, e.g.:
- The upload module is native C code. It is much faster then the python based implementation.
- Long running uploads don't block Zope's thread pool for other incoming requests.
Nginx delivers the uploaded files to zope by means of a shared (distributed) file system. Therefore, nginx and zope must run under the same uid (e.g. www-data) in order to avoid ACL problems during the file transfer process.
In order to avoid unnecessary file system IO Zope's TMPDIR should be on the same volume as Nginx's upload_store (s.a. HOWTO-Blobs-NFS.txt).
These instructions are for Github version.
Then include it in the buildout.cfg:
[buildout]
...
parts = instance
find-links =
http://github.com/hrz-unimr/unimr.external_upload/tarball/master#egg=unimr.external_upload
...
[instance]
...
eggs = unimr.external_upload
effective-user = www-data
...
Here's a nginx site configuration
mysite:
# This specifies which IP and port Plone is running on.
# The default is 127.0.0.1:8080
upstream plone {
server 127.0.0.1:8080;
}
# virtual server
server {
listen 80;
client_max_body_size 1000m;
server_name www.mysite.org;
access_log /var/log/nginx/www.mysite.org.access.log;
error_log /var/log/nginx/www.mysite.org.error.log;
# Note that domain name spelling in VirtualHostBase URL matters
# -> this is what Plone sees as the "real" HTTP request URL.
# "Plone" in the URL is your site id (case sensitive)
location / {
proxy_pass http://plone/VirtualHostBase/http/localhost:8081/Plone/VirtualHostRoot/;
}
# Upload module section
# Upload form should be submitted to this location. In Plone is the correct
# location at any context "atct_edit" for ATContentTypes.
location ~ .*/atct_edit$ {
# Pass altered request body to this location
upload_pass @upload;
# Store files to this directory
# The directory is hashed, subdirectories 0 1 2 3 4 5 6 7 8 9 should exist
upload_store /<path_to_tmpdir>/ngx_upload 1;
# Allow uploaded files to be read/write only by user and group
# Plone has to be run under same uid as nginx
upload_store_access user:rw group:rw;
# Nginx marker for upload field
upload_set_form_field $upload_field_name.ngx_upload "$upload_field_name";
# Set specified fields in request body
upload_set_form_field $upload_field_name.filename "$upload_file_name";
upload_set_form_field $upload_field_name.content_type "$upload_content_type";
upload_set_form_field $upload_field_name.path "$upload_tmp_path";
# Notify backend about checksum and size of a file (currently not used in Plone)
upload_aggregate_form_field "$upload_field_name.md5" "$upload_file_md5";
upload_aggregate_form_field "$upload_field_name.size" "$upload_file_size";
# pass all fields except the file upload field itself
upload_pass_form_field "^.*$";
upload_cleanup 400-599;
}
# Internal location for upload handling
location @upload {
proxy_pass http://plone/VirtualHostBase/http/localhost:8081/Plone/VirtualHostRoot/$request_uri;
}
}