diff --git a/components/multipart-stream-builder.rst b/components/multipart-stream-builder.rst new file mode 100644 index 0000000..120e508 --- /dev/null +++ b/components/multipart-stream-builder.rst @@ -0,0 +1,63 @@ +Multipart Stream Builder +======================== + +A multipart stream is a special kind of stream that is used to transfer files over HTTP. There is currently no PSR-7 support for multipart streams as they are considered to be normal streams with a special content. A multipart stream HTTP request may look like this: + +.. code-block:: none + + POST / HTTP/1.1 + Host: example.com + Content-Type: multipart/form-data; boundary=578de3b0e3c46 + + --578de3b0e3c46 + Content-Disposition: form-data; name="foo" + Content-Length: 15 + + A normal stream + --578de3b0e3c46 + Content-Disposition: form-data; name="bar"; filename="bar.png" + Content-Length: 71 + Content-Type: image/png + + ?PNG +  + ??? + IHDR??? ??? ?????? ???? IDATxc???51?)?:??????IEND?B`? + --578de3b0e3c46 + Content-Type: text/plain + Content-Disposition: form-data; name="baz" + Content-Length: 6 + + string + --578de3b0e3c46-- + + +In the request above you see a set of HTTP headers and a body with two streams. The body starts and ends with a "boundary" and it is also this boundary that separates the streams. That boundary also needs to be specified in the ``Content-Type`` header. + +Building a multipart stream +``````````````````````````` + +To build a multipart stream you may use the ``MultipartStreamBuilder``. It is not coupled to any stream implementation so it needs a ``StreamFactory`` to create the streams. + +.. code-block:: php + + $streamFactory = StreamFactoryDiscovery::find(); + $builder = new MultipartStreamBuilder($streamFactory); + $builder + ->addResource('foo', $stream) + ->addResource('bar', fopen($filePath, 'r'), ['filename' => 'bar.png']) + ->addResource('baz', 'string', ['headers' => ['Content-Type' => 'text/plain']]); + + $multipartStream = $builder->build(); + $boundary = $builder->getBoundary(); + + $request = MessageFactoryDiscovery::find()->createRequest( + 'POST', + 'http://example.com', + ['Content-Type' => 'multipart/form-data; boundary='.$boundary], + $multipartStream + ); + + $response = HttpClientDiscovery::find()->sendRequest($request); + +The second parameter of ``MultipartStreamBuilder::addResource()`` is the content of the stream. The supported input is the same as ``StreamFactory::createStream()``. diff --git a/index.rst b/index.rst index d7b23d0..1e65596 100644 --- a/index.rst +++ b/index.rst @@ -83,6 +83,7 @@ for discussion around a future HTTP client PSR. components/adapter-integration-tests components/promise discovery + components/multipart-stream-builder .. toctree:: :hidden: diff --git a/spelling_word_list.txt b/spelling_word_list.txt index f6fc044..f54f2f4 100644 --- a/spelling_word_list.txt +++ b/spelling_word_list.txt @@ -15,6 +15,7 @@ namespace plugin plugins matchers +multipart param params Puli