After listing files and setting up per directory accesses, we would like to allow some users to upload files.
This solution is very hacky, but it has the advantage of requiring only a standard nginx server and a bit of javaScript.
Nginx Configuration
First, we define our upload endpoint:
...
}
client_body_temp_path
will store request bodies at the specified path on the file system.
However, nginx
will actually do so only if there is a proxy_pass
defined.
To work around this, we define another server that listens only on localhost. With proxy_set_body off;
, the body will not actually be sent to the proxy.
Nginx will create an ever incrementing numbered file for every request body, the increment is non predictable thanks to nginx true randomness1.
Javascript code
To upload files larger than client_max_body_size
and preserve the original filename for the administrator, we'll have to write some client side code.
Using javascript, we can upload a file with an XHR request, and split the file into chunks. Conveniently, browser File
objects have a slice function.
We also send a meta file to allow the server operator to reconstruct the file from its chunks. This file includes metadata such as a magic header, chunk size, chunk count, the size of the last chunk and the filename of each chunk on the server as sent back by nginx (X-fileno).
// files is [File]
files;
With the promise_chain
, each chunk of the file will be uploaded one after the other!
The chunks will be waiting until they are reassembled.
Reassemble with a bash script
Once a file is upload we're left with numbered files in the previously specified directory.
We can reconstruct the original files by searching for all files that start with the marker value #ngxpupload_meta
. With this meta file, we find all chunks of a file and concatenate them into a file named $name
. Finally, we remove all used chunks.
| while ; do
if [; then continue; fi # file still exist
|| if [; then continue; fi # if marker value
IFS='/'
stats=
stats=
stats=
stats=
expected=""
if ; then
expected+="1"
fi
[ || { ; break; }
done
That's the gist of how nginx explorer uploads work!
There are a lot of other cool features in the UI part that I've not wrote about yet and some I've yet to implement.
Don't hesitate to go look at the project page and test nginx explorer ./ngxp.sh servethis
.