examples/http_server_upload.C
is an example of using a
version of
getform
() that handles file uploads
(<input type="file">
elements inside
a <form enctype="multipart/form-data">
.
std::pair<x::http::form::parameters, bool> form=this->getform(req, hasbody, [] (const x::headersbase &headers, const std::string &name_utf8, const std::string &filename_utf8, x::http::form::parameters::base::filereceiver &recv) { // ... recv.receive( [] (const std::vector<char> &chunk) { // ... }, [] { // ... }); }, "iso-8859-1");
Passing two additional arguments to getform
()
enables processing of file uploads, in addition to
getform
() returning the processed form
parameters, as usual. If the form submission did not does not include
file uploads, getform
() processes the form
as usual.
The first additional parameter is a functor. The second parameter
specifies the character set of the field names and non-file upload
field values (“iso-8859-1” in this example).
RFC 2388 specifies that
multipart/form-data
forms must explicitly indicate
each form field name's and value's character set. To properly support
older clients that may not specify the names' and values' character
set, this parameter needs to specify the form's original character.
The file upload version of getform
() converts
all field names and values to UTF-8
in all cases,
and this indicates the character set of field names and values that
do not explicitly specify it.
The functor specified by the first additional parameter gets invoked for each file uploaded through the form. The functor gets invoked more than once if the form uploaded multiple files.
The functor receives four parameters:
The
x::headersbase
parameter provides
the complete MIME headers of the uploaded
file.
The name of the file upload field, and the filename of the uploaded
file, converted to UTF-8
.
The fourth parameter is a native reference to a
x::http::form::parameters::base::filereceiver
object, that has a receive
() method that
the functor must invoke. A “404 not found” exception
gets thrown if the functor returns without invoking
receive
().
The functor/lambda invokes receive
() passing
two more functors or lambdas.
The first “write” functor gets invoked repeatedly with
std::vector<char>
s with the
contents of the uploaded file. The contents of the uploaded file get
processed in small chunks, and the write functor gets invoked
repeatedly until the entire contents of the uploaded file get passed.
The second “close” functor gets invoked after the last
call to the write functor, with the uploaded file's last chunk.
If the uploaded file was empty, the close functor gets invoked without
any preceding call to the write functor.
The write and the close functors do not actually get invoked by
receive
(), but after the parent functor/lambda
returns.
The write functor is responsible for enforcing its own
limits on the maximum size of the
file upload. Calling
x::http::responseimpl::throw_request_entity_too_large
()
throws an exception that results in an HTTP 413
error response to the client.
A form with multiple file uploads results in multiple calls to
getform
()'s functor. Each call invokes
receive
(), passing the write and the close
functor for each file (which may be different for each file in the
form) that subsequently get invoked to process the upload.