Reading a multipart message
To read a message you have to iterate over all its -parts. Then, for each part, you can inspect its headers -and read its body.
Cowboy provides two sets of functions for reading +request bodies as multipart messages.
The cowboy_req:read_part/1,2
functions return the
+next part’s headers, if any.
The cowboy_req:read_part_body/1,2
functions return
+the current part’s body. For large bodies you may
+need to call the function multiple times.
To read a multipart message you need to iterate over +all its parts:
multipart(Req) -> - case cowboy_req:part(Req) of - {ok, _Headers, Req2} -> - {ok, _Body, Req3} = cowboy_req:part_body(Req2), - multipart(Req3); - {done, Req2} -> - Req2 +multipart(Req0) -> + case cowboy_req:read_part(Req0) of + {ok, _Headers, Req1} -> + {ok, _Body, Req} = cowboy_req:read_part_body(Req1), + multipart(Req); + {done, Req} -> + Req end.
Parts do not have a size limit. When a part body is -too big, Cowboy will return what it read so far and -allow you to continue if you wish to do so.
When part bodies are too large, Cowboy will return
+a more
tuple, and allow you to loop until the part
+body has been fully read.
The function cow_multipart:form_data/1
can be used
to quickly obtain information about a part from a
-multipart/form-data
message. This function will
-tell you if the part is for a normal field or if it
-is a file being uploaded.
This can be used for example to allow large part bodies -for files but crash when a normal field is too large.
multipart/form-data
message. The function returns
+a data
or a file
tuple depending on whether this
+is a normal field or a file being uploaded.The following snippet will use this function and +use different strategies depending on whether the +part is a file:
multipart(Req) -> - case cowboy_req:part(Req) of - {ok, Headers, Req2} -> - Req4 = case cow_multipart:form_data(Headers) of +multipart(Req0) -> + case cowboy_req:read_part(Req0) of + {ok, Headers, Req1} -> + Req = case cow_multipart:form_data(Headers) of {data, _FieldName} -> - {ok, _Body, Req3} = cowboy_req:part_body(Req2), - Req3; + {ok, _Body, Req2} = cowboy_req:read_part_body(Req1), + Req2; {file, _FieldName, _Filename, _CType, _CTransferEncoding} -> - stream_file(Req2) + stream_file(Req1) end, - multipart(Req4); - {done, Req2} -> - Req2 + multipart(Req); + {done, Req} -> + Req end. -stream_file(Req) -> - case cowboy_req:part_body(Req) of - {ok, _Body, Req2} -> - Req2; - {more, _Body, Req2} -> - stream_file(Req2) +stream_file(Req0) -> + case cowboy_req:read_part_body(Req0) of + {ok, _Body, Req} -> + Req; + {more, _Body, Req} -> + stream_file(Req) end.
By default the body chunk Cowboy will return is limited
-to 8MB. This can of course be overriden. Both functions
-can take a second argument, the same list of options that
-will be passed to cowboy_req:body/2
function.
Both the part header and body reading functions can take
+options that will be given to the request body reading
+functions. By default, cowboy_req:read_part/1
reads
+up to 64KB for up to 5 seconds. cowboy_req:read_part_body/1
+has the same defaults as cowboy_req:read_body/1
.
To change the defaults for part headers:
cowboy_req:read_part(Req, #{length => 128000}).
And for part bodies:
cowboy_req:read_part_body(Req, #{length => 1000000, period => 7000}).