Skip to content

Commit 68c9653

Browse files
add config options (#23)
1 parent 45636fd commit 68c9653

File tree

3 files changed

+159
-9
lines changed

3 files changed

+159
-9
lines changed

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,40 @@ $adapter = new AzureBlobStorageAdapter(
5555
);
5656
```
5757

58+
### Upload transfer tuning
59+
60+
When writing files, you can control the upload behavior via Flysystem's Config on write/writeStream calls:
61+
62+
- initialTransferSize: int (bytes) — size threshold for first transfer; smaller blobs are uploaded in a single request; larger ones switch to chunked upload.
63+
- maximumTransferSize: int (bytes) — chunk size for block uploads.
64+
- maximumConcurrency: int — number of concurrent workers for parallel uploads.
65+
66+
Example:
67+
68+
```php
69+
use League\Flysystem\Config;
70+
71+
$filesystem->write('path/to/file.txt', $contents, new Config([
72+
'initialTransferSize' => 64 * 1024 * 1024, // 64MB
73+
'maximumTransferSize' => 8 * 1024 * 1024, // 8MB
74+
'maximumConcurrency' => 8,
75+
]));
76+
```
77+
78+
### HTTP headers
79+
80+
```php
81+
$filesystem->write('path/to/file.txt', $contents, new Config([
82+
'httpHeaders' => [
83+
'cacheControl' => 'public, max-age=31536000',
84+
'contentDisposition' => 'inline',
85+
'contentEncoding' => 'gzip',
86+
'contentLanguage' => 'en',
87+
'contentType' => 'text/plain',
88+
],
89+
]));
90+
```
91+
5892
Note that for direct public URLs to work, your container must be configured with public access. If your container is private, you should use the default SAS token approach.
5993

6094
## Documentation

src/AzureBlobStorageAdapter.php

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
use League\Flysystem\UrlGeneration\TemporaryUrlGenerator;
3333
use League\MimeTypeDetection\FinfoMimeTypeDetector;
3434
use League\MimeTypeDetection\MimeTypeDetector;
35+
use AzureOss\FlysystemAzureBlobStorage\Support\ConfigArrayParser;
3536

3637
final class AzureBlobStorageAdapter implements FilesystemAdapter, ChecksumProvider, TemporaryUrlGenerator, PublicUrlGenerator
3738
{
@@ -85,35 +86,96 @@ public function directoryExists(string $path): bool
8586

8687
public function write(string $path, string $contents, Config $config): void
8788
{
88-
$this->upload($path, $contents);
89+
$this->upload($path, $contents, $config);
8990
}
9091

9192
public function writeStream(string $path, $contents, Config $config): void
9293
{
93-
$this->upload($path, $contents);
94+
$this->upload($path, $contents, $config);
9495
}
9596

9697
/**
9798
* @param string|resource $contents
9899
*/
99-
private function upload(string $path, $contents): void
100+
private function upload(string $path, $contents, ?Config $config = null): void
100101
{
101102
try {
102-
$path = $this->prefixer->prefixPath($path);
103-
$mimetype = $this->mimeTypeDetector->detectMimetype($path, $contents);
103+
$options = $this->buildUploadOptionsFromConfig($config);
104104

105-
$options = new UploadBlobOptions(
106-
contentType: $mimetype,
107-
);
105+
if ($options->httpHeaders->contentType === "" && is_string($contents)) {
106+
$options->httpHeaders->contentType = $this->mimeTypeDetector->detectMimeTypeFromBuffer($contents) ?? "";
107+
}
108108

109109
$this->containerClient
110-
->getBlobClient($path)
110+
->getBlobClient($this->prefixer->prefixPath($path))
111111
->upload($contents, $options);
112112
} catch (\Throwable $e) {
113113
throw UnableToWriteFile::atLocation($path, previous: $e);
114114
}
115115
}
116116

117+
private function buildUploadOptionsFromConfig(?Config $config): UploadBlobOptions
118+
{
119+
$options = new UploadBlobOptions();
120+
121+
if ($config === null) {
122+
return $options;
123+
}
124+
125+
$data = $config->toArray();
126+
127+
$initialTransferSize = ConfigArrayParser::parseIntFromArray($data, 'initialTransferSize');
128+
if ($initialTransferSize !== null) {
129+
$options->initialTransferSize = $initialTransferSize;
130+
}
131+
132+
$maximumTransferSize = ConfigArrayParser::parseIntFromArray($data, 'maximumTransferSize');
133+
if ($maximumTransferSize !== null) {
134+
$options->maximumTransferSize = $maximumTransferSize;
135+
}
136+
137+
$maximumConcurrency = ConfigArrayParser::parseIntFromArray($data, 'maximumConcurrency');
138+
if ($maximumConcurrency !== null) {
139+
$options->maximumConcurrency = $maximumConcurrency;
140+
}
141+
142+
$headers = ConfigArrayParser::parseArrayFromArray($data, 'httpHeaders');
143+
if ($headers !== null) {
144+
$cacheControl = ConfigArrayParser::parseStringFromArray($headers, 'cacheControl', 'httpHeaders.');
145+
if ($cacheControl !== null) {
146+
$options->httpHeaders->cacheControl = $cacheControl;
147+
}
148+
149+
$contentDisposition = ConfigArrayParser::parseStringFromArray($headers, 'contentDisposition', 'httpHeaders.');
150+
if ($contentDisposition !== null) {
151+
$options->httpHeaders->contentDisposition = $contentDisposition;
152+
}
153+
154+
$contentEncoding = ConfigArrayParser::parseStringFromArray($headers, 'contentEncoding', 'httpHeaders.');
155+
if ($contentEncoding !== null) {
156+
$options->httpHeaders->contentEncoding = $contentEncoding;
157+
}
158+
159+
$contentHash = ConfigArrayParser::parseStringFromArray($headers, 'contentHash', 'httpHeaders.');
160+
if ($contentHash !== null) {
161+
$options->httpHeaders->contentHash = $contentHash;
162+
}
163+
164+
$contentLanguage = ConfigArrayParser::parseStringFromArray($headers, 'contentLanguage', 'httpHeaders.');
165+
if ($contentLanguage !== null) {
166+
$options->httpHeaders->contentLanguage = $contentLanguage;
167+
}
168+
169+
$contentType = ConfigArrayParser::parseStringFromArray($headers, 'contentType', 'httpHeaders.');
170+
if ($contentType !== null) {
171+
$options->httpHeaders->contentType = $contentType;
172+
}
173+
}
174+
175+
return $options;
176+
}
177+
178+
117179
public function read(string $path): string
118180
{
119181
try {

src/Support/ConfigArrayParser.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace AzureOss\FlysystemAzureBlobStorage\Support;
6+
7+
final class ConfigArrayParser
8+
{
9+
/**
10+
* @param array<string, mixed> $data
11+
*/
12+
public static function parseIntFromArray(array $data, string $key): ?int
13+
{
14+
if (!array_key_exists($key, $data) || $data[$key] === null) {
15+
return null;
16+
}
17+
if (!is_int($data[$key])) {
18+
throw new \RuntimeException(sprintf('%s must be an int.', $key));
19+
}
20+
return $data[$key];
21+
}
22+
23+
/**
24+
* @param array<string, mixed> $data
25+
* @return array<string, mixed>|null
26+
*/
27+
public static function parseArrayFromArray(array $data, string $key): ?array
28+
{
29+
$value = $data[$key] ?? null;
30+
if ($value === null) {
31+
return null;
32+
}
33+
if (!is_array($value)) {
34+
throw new \RuntimeException(sprintf('%s must be an array.', $key));
35+
}
36+
return $value;
37+
}
38+
39+
/**
40+
* @param array<string, mixed> $data
41+
*/
42+
public static function parseStringFromArray(array $data, string $key, string $contextPrefix = ''): ?string
43+
{
44+
$value = $data[$key] ?? null;
45+
if ($value === null) {
46+
return null;
47+
}
48+
if (!is_string($value)) {
49+
$fullKey = $contextPrefix !== '' ? $contextPrefix . $key : $key;
50+
throw new \RuntimeException(sprintf('%s must be a string.', $fullKey));
51+
}
52+
return $value;
53+
}
54+
}

0 commit comments

Comments
 (0)