Skip to content

Commit

Permalink
Improve multi-part requests (#10)
Browse files Browse the repository at this point in the history
* Improve multi-part requests

* Add return type

* Revert "Add return type"

This reverts commit 589bea3.

* Revert return type

* Remove resource as accepted type

* Use iterable
  • Loading branch information
jenky committed May 6, 2023
1 parent 2fe9dca commit 3a698ce
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 204 deletions.
13 changes: 11 additions & 2 deletions docs/basic/requests.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ final class MyRequest extends Request

### Multi-part requests

If you would like to send files as multi-part requests, you should create your file using `Jenky\Atlas\Body\Multipart` class. This class accept:
If you would like to send files as multi-part requests, you should create your file using `Jenky\Atlas\Body\MultipartResource::from()` static method. This method accepts:
- `resource` stream.
- `string` the file absolute path in the system.
- `Psr\Http\Message\UploadedFileInterface` instance.
- [`SplFileObject`](https://www.php.net/manual/en/class.splfileobject.php) instance.
Expand All @@ -139,12 +140,20 @@ final class MyRequest extends Request
return [
'hero_name' => 'Superman',
'name' => 'Clark Kent',
'avatar' => new Multipart(__DIR__.'/../path_to_image'),
'avatar' => MultipartResource::from(__DIR__.'/../path_to_image.png'),
];
}
}
```

You can also pass the second parameter as the filename and third parameter as content type of the file.

```php
$request = new MyRequest();

$request->with('image', MultipartResource::from(__DIR__.'/../path_to_image.jpg', 'image.jpeg', 'image/jpeg'));
```

!!!
You can create your own multipart file to fit your application logic. It must implement the `Jenky\Atlas\Contracts\MultipartInterface`.
!!!
Expand Down
170 changes: 0 additions & 170 deletions src/Body/Multipart.php

This file was deleted.

39 changes: 15 additions & 24 deletions src/Body/MultipartPayload.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Jenky\Atlas\Contracts\MultipartInterface;
use Jenky\Atlas\Contracts\PayloadInterface;
use Jenky\Atlas\Map;
use Psr\Http\Message\StreamInterface;

final class MultipartPayload extends Map implements PayloadInterface
{
Expand All @@ -16,11 +17,6 @@ final class MultipartPayload extends Map implements PayloadInterface
*/
private $boundary;

/**
* @var \Psr\Http\Message\StreamFactoryInterface
*/
protected $streamFactory;

/**
* Create new multipart payload instance.
*
Expand All @@ -33,7 +29,6 @@ public function __construct(array $parameters = [], ?string $boundary = null)
parent::__construct($parameters);

$this->boundary = $boundary ?: bin2hex(random_bytes(20));
$this->streamFactory = Psr17FactoryDiscovery::findStreamFactory();
}

/**
Expand All @@ -47,21 +42,17 @@ public function contentType(): ?string
/**
* Gather all the parts.
*/
private function parts(): array
private function parts(): iterable
{
$parts = [];

foreach ($this->all() as $key => $value) {
$parts[] = $this->part($key, $value);
yield $this->part($key, $value);
}

return $parts;
}

/**
* Build a single part.
*
* @param mixed $value
* @param string|MultipartInterface|StreamInterface $value
*/
private function part(string $name, $value): string
{
Expand All @@ -71,20 +62,20 @@ private function part(string $name, $value): string
);

if ($value instanceof MultipartInterface) {
$stream = $value->stream();

if ($value->isFile()) {
if ($filename = $value->filename()) {
$headers['Content-Disposition'] .= sprintf('; filename="%s"', basename($filename));
}
if ($filename = $value->filename()) {
$headers['Content-Disposition'] .= sprintf('; filename="%s"', basename($filename));
}

// Set a default Content-Type
if ($type = $value->mimeType()) {
$headers['Content-Type'] = $type;
}
// Set a default Content-Type
if ($type = $value->mimeType()) {
$headers['Content-Type'] = $type;
}

$stream = $value->stream();
} else {
$stream = $this->streamFactory->createStream($value);
$stream = $value instanceof StreamInterface
? $value
: Psr17FactoryDiscovery::findStreamFactory()->createStream($value);
}

// Set a default content-length header
Expand Down
Loading

0 comments on commit 3a698ce

Please sign in to comment.