Feature request: Option to pass file metadata on file stream itself
See original GitHub issueRequest doesn’t currently have any logic to do transfer-encoding: chunked
. It currently tries to always send a content-length
header, but form-data
cannot just pull that number out of thin air without processing the whole stream.
Ordinarily, this would be solved by passing the knownLength
file option, either to form-data
directly or to request
, however this is not possible when using libraries that themselves use request
, such as box-node-sdk
.
Currently, I am working around this by taking advantage of form-data
’s automatic detection of content-length
headers on IncomingMessage
instances and its use of the name
prop (presumably from Browser File
objects) to derive the mime-type, though this also means I’m having the client-side code send the file meta along side the file content itself.
myStream.httpVersion = '1.0'; // value technically doesn't matter, but might as well use a valid value.
myStream.headers = { 'content-length': myStreamKnownLength };
myStream.name = myStreamFileName;
However, it would be nice if there were a more sanctioned way to do this, something like:
myStream._formDataOptions = {
filename: myStreamFileName,
knownLength: myStreamKnownLength,
};
Aside: While
box-node-sdk
lets you pass additional base options torequest
, i’m not sure every library that usesrequest
does this, so even ifrequest
did supporttransfer-encoding: chunked
I’m not certain the end user would always be able to specify that. Being able to pass the file meta straight on the file stream without resorting to trickingform-data
would ensure some sort of escape hatch for those end users.
I’m open to doing up a PR if the idea presented here is acceptable.
Issue Analytics
- State:
- Created 6 years ago
- Comments:9 (4 by maintainers)
Top GitHub Comments
I probably should have provided a concrete example of my issue!
My primary concern is not with passing data to
form-data
itself, since I could just passknownLength
directly and be done with it, nor with passing data torequest
since that lets you also specify the options to pass toform-data
includingknownLength
. Rather, it is with libraries that do not expose the object handed torequest
at all.For instance, when using the
box-node-sdk
, you can pass some additional options to it to configure all requests it makes usingrequest
, but you can’t configure individual requests, and you can’t pass different options for requests which upload versus those which don’t, and you don’t directly create anything for the request body itself.Basically, when uploading a file, all you have access to is this:
That goes through a couple layers until it finally reaches the internal wrapper around
request
, but the user ofbox-node-sdk
never never gets to actually see any of that, let alone whenrequest
builds the body usingform-data
.This means while something like the following work:
This does not:
Or, more specific to my case, using
busboy
to handlemultipart/form-data
requests from the client:In this case, the file will fail to upload because the
file
stream created by Busboy does not have any information on it thatform-data
can use to determine aknownSize
. TheboxClient
frombox-node-sdk
builds a request object to pass torequest
, including theformData
option which causes it to create a body usingform-data
.request
then asksform-data
what size the body is going to be because it wants to create acontent-length
header, but as thefile
stream created by busboy does not have any metadata on it, neither in the style of aReadStream
nor anIncomingMessage
,form-data
tellsrequest
a smaller size, andrequest
then sets thecontent-length
header with that smaller size, and the request body is truncated and the request closed prematurely.In my specific case, I got around this by making the client send file metadata before the file itself and then using the above trickery to make
form-data
pick up on that metadata:Hope that explains the sort of situations I’m concerned with!
As an extra vote for this: just spent 2 hours trying to figure out https://github.com/request/request/issues/2499. Currently form-data is broken for anything other than the 3 supported stream types (fs readstreams, request streams and httpIncoming) when really all it needs to know is the file size. I ended up doing something similar to whats described here: adding fake httpVersion and content-length headers, and that worked. A standard way to specify the size for arbitrary stream-compatible objects would really be the way to go.