tiny-oss 0.5.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +459 -52
- package/UPGRADING.md +151 -0
- package/dist/aws.d.ts +208 -0
- package/dist/azure.d.ts +204 -0
- package/dist/cos.d.ts +208 -0
- package/dist/index.d.ts +209 -0
- package/dist/obs.d.ts +208 -0
- package/dist/protocol.d.ts +271 -0
- package/dist/tiny-oss.aws.es.js +1052 -0
- package/dist/tiny-oss.aws.es.js.map +1 -0
- package/dist/tiny-oss.azure.es.js +882 -0
- package/dist/tiny-oss.azure.es.js.map +1 -0
- package/dist/tiny-oss.cos.es.js +984 -0
- package/dist/tiny-oss.cos.es.js.map +1 -0
- package/dist/tiny-oss.es.js +965 -0
- package/dist/tiny-oss.es.js.map +1 -0
- package/dist/tiny-oss.obs.es.js +1048 -0
- package/dist/tiny-oss.obs.es.js.map +1 -0
- package/dist/tiny-oss.protocol.es.js +588 -0
- package/dist/tiny-oss.protocol.es.js.map +1 -0
- package/package.json +78 -64
- package/dist/tiny-oss.js +0 -1642
- package/dist/tiny-oss.js.map +0 -1
- package/dist/tiny-oss.min.js +0 -35
- package/dist/tiny-oss.min.js.map +0 -1
- package/es/TinyOSS.js +0 -209
- package/es/index.js +0 -1
- package/es/utils/ajax.js +0 -61
- package/es/utils/index.js +0 -188
- package/lib/TinyOSS.js +0 -218
- package/lib/index.js +0 -3
- package/lib/utils/ajax.js +0 -66
- package/lib/utils/index.js +0 -203
- package/types/index.d.ts +0 -89
- package/vendor/digest.js +0 -390
package/README.md
CHANGED
|
@@ -1,11 +1,29 @@
|
|
|
1
1
|
# tiny-oss
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/tiny-oss)
|
|
4
4
|
|
|
5
5
|
**English | [简体中文](README_zh-CN.md)**
|
|
6
6
|
|
|
7
|
+
A tiny object storage SDK focused on uploading: Aliyun OSS, Tencent Cloud COS, Huawei Cloud OBS, AWS S3 (plus S3-compatible stores) and Azure Blob Storage under one core API; runs in browsers, Node.js, Service Workers and WeChat mini programs; extensible with custom providers. About 11kb (min+gzipped) for the full entry — tree-shaking drops the operations you don't import, so a bundle that only calls `put` is smaller.
|
|
8
|
+
|
|
9
|
+
**Upgrading from 0.x? See the [upgrade guide](UPGRADING.md).**
|
|
10
|
+
|
|
11
|
+
## Supported providers
|
|
12
|
+
|
|
13
|
+
- [Aliyun OSS (`tiny-oss`)](#usage) — the default entry
|
|
14
|
+
- [AWS S3 (`tiny-oss/aws`)](#aws-s3) — SigV4 signing; also drives S3-compatible stores such as [MinIO, Cloudflare R2 and Google Cloud Storage](#s3-compatible-stores-minio-cloudflare-r2-google-cloud-storage-)
|
|
15
|
+
- [Azure Blob Storage (`tiny-oss/azure`)](#azure-blob-storage)
|
|
16
|
+
- [Huawei Cloud OBS (`tiny-oss/obs`)](#huawei-cloud-obs)
|
|
17
|
+
- [Tencent Cloud COS (`tiny-oss/cos`)](#tencent-cloud-cos)
|
|
18
|
+
|
|
7
19
|
## Installation
|
|
8
20
|
|
|
21
|
+
pnpm
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
pnpm add tiny-oss
|
|
25
|
+
```
|
|
26
|
+
|
|
9
27
|
Npm
|
|
10
28
|
|
|
11
29
|
```sh
|
|
@@ -20,116 +38,505 @@ yarn add tiny-oss
|
|
|
20
38
|
|
|
21
39
|
## Usage
|
|
22
40
|
|
|
41
|
+
Every operation is a standalone function taking the client options as the first argument. Import only what you use and bundlers tree-shake the rest, so a bundle that only calls `put` does not carry the multipart code.
|
|
42
|
+
|
|
23
43
|
### Basic
|
|
24
44
|
|
|
25
45
|
```js
|
|
26
|
-
|
|
46
|
+
import { put } from 'tiny-oss';
|
|
47
|
+
|
|
48
|
+
const blob = new Blob(['hello world'], { type: 'text/plain' });
|
|
49
|
+
|
|
50
|
+
// Upload
|
|
51
|
+
put(
|
|
52
|
+
{
|
|
53
|
+
accessKeyId: 'your accessKeyId',
|
|
54
|
+
accessKeySecret: 'your accessKeySecret',
|
|
55
|
+
// Recommend to use the stsToken option in browser
|
|
56
|
+
stsToken: 'security token',
|
|
57
|
+
region: 'oss-cn-beijing',
|
|
58
|
+
bucket: 'your bucket'
|
|
59
|
+
},
|
|
60
|
+
'hello-world',
|
|
61
|
+
blob
|
|
62
|
+
);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Available functions: `put`, `putSymlink`, `signatureUrl`, `initMultipartUpload`, `uploadPart`, `completeMultipartUpload`, `abortMultipartUpload`, `listParts`, `listUploads`, `uploadPartCopy`, `multipartUpload`, `bindOptions`.
|
|
66
|
+
|
|
67
|
+
Types are available via named imports: `import { put, type Options, type BlobLike, type PutOptions, type Progress, type SignatureUrlOptions } from 'tiny-oss'`.
|
|
68
|
+
|
|
69
|
+
### Binding options once
|
|
70
|
+
|
|
71
|
+
To avoid passing the credentials on every call, bind them once with `bindOptions`. It only references the operation you give it, so tree shaking is unaffected:
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
import { put, bindOptions } from 'tiny-oss';
|
|
75
|
+
|
|
76
|
+
const upload = bindOptions(put, {
|
|
27
77
|
accessKeyId: 'your accessKeyId',
|
|
28
78
|
accessKeySecret: 'your accessKeySecret',
|
|
29
|
-
// Recommend to use the stsToken option in browser
|
|
30
79
|
stsToken: 'security token',
|
|
31
80
|
region: 'oss-cn-beijing',
|
|
32
81
|
bucket: 'your bucket'
|
|
33
82
|
});
|
|
34
83
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
// Upload
|
|
38
|
-
oss.put('hello-world', blob);
|
|
84
|
+
upload('hello-world', new Blob(['hello world'], { type: 'text/plain' }));
|
|
39
85
|
```
|
|
40
86
|
|
|
41
87
|
### Upload progress
|
|
42
88
|
|
|
43
|
-
You can specify the
|
|
89
|
+
You can specify the last parameter to monitor the upload progress data:
|
|
44
90
|
|
|
45
91
|
```js
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
92
|
+
put(
|
|
93
|
+
options,
|
|
94
|
+
'hello-world',
|
|
95
|
+
blob,
|
|
96
|
+
{
|
|
97
|
+
onprogress (e) {
|
|
98
|
+
console.log('total: ', e.total, ', uploaded: ', e.loaded);
|
|
99
|
+
}
|
|
50
100
|
}
|
|
51
|
-
|
|
101
|
+
);
|
|
52
102
|
```
|
|
53
103
|
|
|
54
104
|
More options or methods see [API](#api).
|
|
55
105
|
|
|
56
|
-
|
|
106
|
+
### Protocol
|
|
57
107
|
|
|
58
|
-
|
|
108
|
+
The `Protocol` interface (`tiny-oss/protocol`):
|
|
59
109
|
|
|
60
|
-
|
|
110
|
+
| field | meaning |
|
|
111
|
+
|---|---|
|
|
112
|
+
| `request(options, params)` | Sign and send one request through the configured transport; resolve `{ data, headers, status, statusText }` |
|
|
113
|
+
| `signUrl(options, objectName, urlOptions)` | Build a signed download URL |
|
|
114
|
+
| `metaPrefix` | Object metadata header prefix, e.g. `'x-my-meta-'` |
|
|
115
|
+
| `copySourceHeader` / `copySourceRangeHeader` | Header names for `uploadPartCopy` |
|
|
116
|
+
| `listUploadsMarkerKey` | Query key for the list-uploads marker (`'marker'` OSS-style, `'key-marker'` S3-style) |
|
|
117
|
+
| `supportsSymlink` | Whether `putSymlink` is exported (`false` when the provider has no symlink API) |
|
|
61
118
|
|
|
62
|
-
|
|
63
|
-
* Edge >= 12
|
|
64
|
-
* IE >= 10
|
|
65
|
-
* Firefox >= 4
|
|
66
|
-
* Safari >= 8
|
|
67
|
-
* Opera >= 11
|
|
68
|
-
* Android >= 4.4.4
|
|
69
|
-
* iOS >= 8
|
|
119
|
+
`request` receives `{ verb, objectName, contentMd5, headers, subResource, data, timeout, onprogress }`; `subResource` is the query-parameter map the operations build (`{ uploads: '' }`, `{ partNumber, uploadId }`, …) — the request implementation decides which of them participate in the signature.
|
|
70
120
|
|
|
71
|
-
|
|
121
|
+
The shared helpers `normalizeOptions`, `resolveTimeout` and `dataSize` (also exported from `tiny-oss/protocol`) cover option defaults, timeout and payload sizing for the `request` implementation. Because each entry is a separate build, a custom provider never inflates the OSS bundle — import it from its own file.
|
|
72
122
|
|
|
73
|
-
|
|
123
|
+
### Compatibility
|
|
124
|
+
|
|
125
|
+
It should work in most browsers, as well as Node.js, Service Workers and WeChat mini programs (see [Non-browser environments](#non-browser-environments)).
|
|
126
|
+
|
|
127
|
+
This package depends on some Web APIs, such as [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob), [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array), [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). In browsers it uses `XMLHttpRequest` for network requests; other environments inject their own transport (see below).
|
|
128
|
+
|
|
129
|
+
### Non-browser environments
|
|
130
|
+
|
|
131
|
+
The network layer is injectable. Browsers use `XMLHttpRequest` by default;
|
|
132
|
+
Service Workers and WeChat mini programs have ready-made adapters:
|
|
74
133
|
|
|
75
134
|
```js
|
|
76
|
-
|
|
135
|
+
// Service Worker (or Node.js)
|
|
136
|
+
import { setTransport, fetchTransport } from 'tiny-oss';
|
|
137
|
+
setTransport(fetchTransport);
|
|
138
|
+
|
|
139
|
+
// WeChat mini program
|
|
140
|
+
import { setTransport, wxRequestTransport } from 'tiny-oss';
|
|
141
|
+
setTransport(wxRequestTransport);
|
|
77
142
|
```
|
|
78
143
|
|
|
79
|
-
|
|
144
|
+
The input data types are environment agnostic: `Blob`, `ArrayBuffer`,
|
|
145
|
+
`Uint8Array` and plain strings are all accepted (mini programs don't have
|
|
146
|
+
`Blob`, so pass `ArrayBuffer`).
|
|
147
|
+
|
|
148
|
+
#### WeChat mini program upload
|
|
149
|
+
|
|
150
|
+
```js
|
|
151
|
+
import { put, multipartUpload } from 'tiny-oss';
|
|
152
|
+
|
|
153
|
+
const arrayBuffer = getFileArrayBuffer(); // e.g. from FileSystemManager.readFile
|
|
154
|
+
|
|
155
|
+
put(options, 'photo.jpg', arrayBuffer);
|
|
156
|
+
multipartUpload(options, 'video.mp4', arrayBuffer, { partSize: 1024 * 1024 });
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### Custom transport
|
|
160
|
+
|
|
161
|
+
For other environments, pass your own function to `setTransport`. It receives
|
|
162
|
+
`(url, { method, headers, data, timeout, onprogress, total })` and must
|
|
163
|
+
resolve with `{ data, headers, status, statusText }`, rejecting on failure:
|
|
164
|
+
|
|
165
|
+
```js
|
|
166
|
+
setTransport(async (url, { method, headers, data, timeout }) => {
|
|
167
|
+
// adapt to your platform's request API
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### Progress events
|
|
172
|
+
|
|
173
|
+
`onprogress` receives `{ loaded, total, lengthComputable }`. Browsers report
|
|
174
|
+
real upload progress (`lengthComputable: true`). `fetch` and `wx.request`
|
|
175
|
+
cannot report intermediate progress, so those adapters fire a `0%` event
|
|
176
|
+
before sending and a `100%` event after, with `lengthComputable: false` — use
|
|
177
|
+
them to toggle a loading state, not to render a percentage.
|
|
178
|
+
|
|
179
|
+
## Providers
|
|
180
|
+
|
|
181
|
+
### AWS S3
|
|
182
|
+
|
|
183
|
+
The same operations are available for AWS S3 through a dedicated entry point (`tiny-oss/aws`). Each entry is self-contained: importing only what you use keeps the OSS bundle free of COS/OBS/S3 signing code and vice versa.
|
|
80
184
|
|
|
81
|
-
|
|
185
|
+
```js
|
|
186
|
+
import { put, multipartUpload, signatureUrl } from 'tiny-oss/aws';
|
|
187
|
+
|
|
188
|
+
put(
|
|
189
|
+
{
|
|
190
|
+
accessKeyId: 'your Access Key ID',
|
|
191
|
+
accessKeySecret: 'your Secret Access Key',
|
|
192
|
+
// Recommend to use the stsToken option in browser
|
|
193
|
+
stsToken: 'security token',
|
|
194
|
+
region: 'us-west-2',
|
|
195
|
+
bucket: 'your-bucket'
|
|
196
|
+
},
|
|
197
|
+
'hello-world',
|
|
198
|
+
blob
|
|
199
|
+
);
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
The AWS entry exports everything the OSS entry does except `putSymlink` (S3 has no symlink API). Options:
|
|
203
|
+
|
|
204
|
+
| option | type | description |
|
|
205
|
+
|---|---|---|
|
|
206
|
+
| `accessKeyId` | `string` | AWS Access Key ID |
|
|
207
|
+
| `accessKeySecret` | `string` | AWS Secret Access Key |
|
|
208
|
+
| `stsToken` | `string` | temporary-credential SessionToken (`x-amz-security-token`) |
|
|
209
|
+
| `region` | `string` | e.g. `us-east-1`, `ap-southeast-1` |
|
|
210
|
+
| `bucket` | `string` | plain bucket name |
|
|
211
|
+
| `endpoint` | `string` | custom endpoint, no protocol prefix (the `secure` option selects it) |
|
|
212
|
+
| `secure` | `boolean` | use HTTPS (`true`) or HTTP (`false`), default `false` |
|
|
213
|
+
| `timeout` | `string \| number` | instance-level timeout for all operations, default 60s |
|
|
82
214
|
|
|
83
|
-
|
|
84
|
-
* accessKeySecret
|
|
85
|
-
* stsToken
|
|
86
|
-
* bucket
|
|
87
|
-
* endpoint
|
|
88
|
-
* region
|
|
89
|
-
* secure
|
|
90
|
-
* timeout
|
|
215
|
+
Notes:
|
|
91
216
|
|
|
92
|
-
|
|
217
|
+
- Browser uploads to S3 require the bucket's CORS rule to allow your origin and expose the `ETag` response header for multipart uploads; temporary credentials (STS) are recommended over permanent keys.
|
|
218
|
+
- The signer implements SigV4 with `UNSIGNED-PAYLOAD` (the official SDK disables body signing for S3), so it is byte-identical to `aws-sdk` v2.
|
|
219
|
+
- Signatures are time-sensitive; a skewed client clock yields `403 RequestTimeTooSkewed`.
|
|
220
|
+
|
|
221
|
+
#### S3-compatible stores (MinIO, Cloudflare R2, Google Cloud Storage, …)
|
|
222
|
+
|
|
223
|
+
S3-compatible stores speak SigV4, so the `tiny-oss/aws` entry works with **zero extra code** — just point the `endpoint` at the store and enable `pathStyle` (these stores address buckets in the URL path, like the official SDK's `forcePathStyle`):
|
|
224
|
+
|
|
225
|
+
```js
|
|
226
|
+
import { put, signatureUrl, multipartUpload } from 'tiny-oss/aws';
|
|
227
|
+
|
|
228
|
+
// MinIO
|
|
229
|
+
await put(
|
|
230
|
+
{
|
|
231
|
+
accessKeyId: 'minioadmin',
|
|
232
|
+
accessKeySecret: 'minioadmin',
|
|
233
|
+
region: 'us-east-1',
|
|
234
|
+
bucket: 'my-bucket',
|
|
235
|
+
endpoint: 'minio.example.com', // no protocol prefix
|
|
236
|
+
pathStyle: true,
|
|
237
|
+
},
|
|
238
|
+
'hello-world',
|
|
239
|
+
blob
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
// Cloudflare R2 — region is always 'auto'
|
|
243
|
+
await put(
|
|
244
|
+
{
|
|
245
|
+
accessKeyId: 'your R2 Access Key ID',
|
|
246
|
+
accessKeySecret: 'your R2 Secret Access Key',
|
|
247
|
+
region: 'auto',
|
|
248
|
+
bucket: 'my-bucket',
|
|
249
|
+
endpoint: '<accountid>.r2.cloudflarestorage.com',
|
|
250
|
+
pathStyle: true,
|
|
251
|
+
},
|
|
252
|
+
'hello-world',
|
|
253
|
+
blob
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
// Google Cloud Storage — XML API's AWS SigV4-compatible mode.
|
|
257
|
+
// Create an HMAC key in the Cloud Console first; region is 'auto'.
|
|
258
|
+
await put(
|
|
259
|
+
{
|
|
260
|
+
accessKeyId: 'your GCS HMAC access id',
|
|
261
|
+
accessKeySecret: 'your GCS HMAC secret',
|
|
262
|
+
region: 'auto',
|
|
263
|
+
bucket: 'my-bucket',
|
|
264
|
+
endpoint: 'storage.googleapis.com',
|
|
265
|
+
pathStyle: true,
|
|
266
|
+
},
|
|
267
|
+
'hello-world',
|
|
268
|
+
blob
|
|
269
|
+
);
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
The endpoint must not carry a protocol (`http://`/`https://`) — the `secure` option selects it. Every operation (`put`, multipart, list, copy, signed URLs) works unchanged against these stores.
|
|
273
|
+
|
|
274
|
+
Not every store speaks S3: Azure Blob Storage uses its own SharedKey signing and a different multipart model (block blobs), so it is not covered by the AWS entry.
|
|
275
|
+
|
|
276
|
+
### Tencent Cloud COS
|
|
277
|
+
|
|
278
|
+
The same operations are available for Tencent Cloud COS through a separate entry point. The OSS entry never references COS code and vice versa, so importing only what you use keeps the OSS bundle free of COS signing code (and the other way around).
|
|
279
|
+
|
|
280
|
+
```js
|
|
281
|
+
import { put, multipartUpload, signatureUrl } from 'tiny-oss/cos';
|
|
282
|
+
|
|
283
|
+
put(
|
|
284
|
+
{
|
|
285
|
+
accessKeyId: 'your SecretId',
|
|
286
|
+
accessKeySecret: 'your SecretKey',
|
|
287
|
+
// Recommend to use the stsToken option in browser
|
|
288
|
+
stsToken: 'security token',
|
|
289
|
+
region: 'ap-guangzhou',
|
|
290
|
+
bucket: 'your-bucket-1250000000' // COS bucket names include the APPID suffix
|
|
291
|
+
},
|
|
292
|
+
'hello-world',
|
|
293
|
+
blob
|
|
294
|
+
);
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
The COS entry exports everything the OSS entry does except `putSymlink` (COS has no symlink API). Options:
|
|
298
|
+
|
|
299
|
+
| option | type | description |
|
|
300
|
+
|---|---|---|
|
|
301
|
+
| `accessKeyId` | `string` | Tencent SecretId |
|
|
302
|
+
| `accessKeySecret` | `string` | Tencent SecretKey |
|
|
303
|
+
| `stsToken` | `string` | temporary-credential SecurityToken (`x-cos-security-token`) |
|
|
304
|
+
| `region` | `string` | e.g. `ap-guangzhou` |
|
|
305
|
+
| `bucket` | `string` | must include the APPID suffix, e.g. `examplebucket-1250000000` |
|
|
306
|
+
| `endpoint` | `string` | custom endpoint, no protocol prefix (the `secure` option selects it) |
|
|
307
|
+
| `secure` | `boolean` | use HTTPS (`true`) or HTTP (`false`), default `false` |
|
|
308
|
+
| `timeout` | `string \| number` | instance-level timeout for all operations, default 60s |
|
|
309
|
+
|
|
310
|
+
Notes:
|
|
311
|
+
|
|
312
|
+
- Like OSS, browser uploads to COS require a CORS rule on the bucket, and temporary credentials (CAM STS) are recommended over permanent keys.
|
|
313
|
+
- Set the bucket CORS rule to expose the `ETag` response header for multipart uploads.
|
|
314
|
+
- COS signatures are time-sensitive; a skewed client clock yields 403 `RequestTimeTooSkewed`.
|
|
315
|
+
|
|
316
|
+
### Huawei Cloud OBS
|
|
317
|
+
|
|
318
|
+
The same operations are also available for Huawei Cloud OBS through a dedicated entry point (`tiny-oss/obs`). Each entry is self-contained: importing only what you use keeps the OSS bundle free of COS/OBS signing code and vice versa.
|
|
319
|
+
|
|
320
|
+
```js
|
|
321
|
+
import { put, multipartUpload, signatureUrl } from 'tiny-oss/obs';
|
|
322
|
+
|
|
323
|
+
put(
|
|
324
|
+
{
|
|
325
|
+
accessKeyId: 'your Access Key Id',
|
|
326
|
+
accessKeySecret: 'your Secret Access Key',
|
|
327
|
+
// Recommend to use the stsToken option in browser
|
|
328
|
+
stsToken: 'security token',
|
|
329
|
+
region: 'cn-north-4',
|
|
330
|
+
bucket: 'your-bucket' // OBS bucket names carry no suffix
|
|
331
|
+
},
|
|
332
|
+
'hello-world',
|
|
333
|
+
blob
|
|
334
|
+
);
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
The OBS entry exports everything the OSS entry does except `putSymlink` (OBS has no symlink API). Options:
|
|
338
|
+
|
|
339
|
+
| option | type | description |
|
|
340
|
+
|---|---|---|
|
|
341
|
+
| `accessKeyId` | `string` | Huawei Cloud Access Key Id |
|
|
342
|
+
| `accessKeySecret` | `string` | Huawei Cloud Secret Access Key |
|
|
343
|
+
| `stsToken` | `string` | temporary-credential SecurityToken (`x-obs-security-token`) |
|
|
344
|
+
| `region` | `string` | e.g. `cn-north-4`, `cn-east-3` |
|
|
345
|
+
| `bucket` | `string` | plain bucket name (no APPID suffix) |
|
|
346
|
+
| `endpoint` | `string` | custom endpoint, no protocol prefix (the `secure` option selects it) |
|
|
347
|
+
| `secure` | `boolean` | use HTTPS (`true`) or HTTP (`false`), default `false` |
|
|
348
|
+
| `timeout` | `string \| number` | instance-level timeout for all operations, default 60s |
|
|
349
|
+
|
|
350
|
+
Notes:
|
|
351
|
+
|
|
352
|
+
- Browser uploads to OBS require the bucket's CORS rule to allow your origin and expose the `ETag` response header for multipart uploads; temporary credentials (IAM agency) are recommended over permanent keys.
|
|
353
|
+
- OBS signatures are time-sensitive (the `x-obs-date` header); a skewed client clock yields `403 RequestTimeTooSkewed`.
|
|
354
|
+
- The OBS signer uses the OBS "obs" signature scheme, matching the official `esdk-obs-browserjs` byte for byte.
|
|
355
|
+
|
|
356
|
+
### Azure Blob Storage
|
|
357
|
+
|
|
358
|
+
Azure Blob Storage speaks neither SigV4 nor any of the other schemes above: it uses its own **SharedKey** authorization and a different multipart model (block blobs). A dedicated entry point (`tiny-oss/azure`) implements both, so the API stays the same:
|
|
359
|
+
|
|
360
|
+
```js
|
|
361
|
+
import { put, multipartUpload, signatureUrl } from 'tiny-oss/azure';
|
|
362
|
+
|
|
363
|
+
put(
|
|
364
|
+
{
|
|
365
|
+
accessKeyId: 'your storage account name',
|
|
366
|
+
accessKeySecret: 'your base64 account key',
|
|
367
|
+
bucket: 'your-container'
|
|
368
|
+
},
|
|
369
|
+
'hello-world',
|
|
370
|
+
blob
|
|
371
|
+
);
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
The Azure entry exports `put`, `signatureUrl`, `initMultipartUpload`, `uploadPart`, `completeMultipartUpload`, `multipartUpload` and `bindOptions`. Options:
|
|
375
|
+
|
|
376
|
+
| option | type | description |
|
|
377
|
+
|---|---|---|
|
|
378
|
+
| `accessKeyId` | `string` | storage account name |
|
|
379
|
+
| `accessKeySecret` | `string` | the **base64** account key (used after base64-decoding, per SharedKey) |
|
|
380
|
+
| `bucket` | `string` | container name |
|
|
381
|
+
| `region` | `string` | not used (no region concept in the Blob service) |
|
|
382
|
+
| `stsToken` | `string` | not used (use a SAS or stored access policy instead) |
|
|
383
|
+
| `endpoint` | `string` | custom endpoint, no protocol prefix |
|
|
384
|
+
| `secure` | `boolean` | use HTTPS (`true`) or HTTP (`false`), default `true` |
|
|
385
|
+
| `timeout` | `string \| number` | instance-level timeout for all operations, default 60s |
|
|
386
|
+
|
|
387
|
+
Notes:
|
|
388
|
+
|
|
389
|
+
- Every request carries `x-ms-date` and `x-ms-version`; the StringToSign is the 12-field SharedKey format with canonicalized `x-ms-*` headers and the canonicalized resource, verified byte-for-byte against `@azure/storage-common` and the MSDN example.
|
|
390
|
+
- `signatureUrl` returns a service SAS (`sv=2020-12-06`, `sr=b`), byte-identical to `@azure/storage-blob`'s `generateBlobSASQueryParameters`. It is valid immediately; `method: 'PUT'` grants write.
|
|
391
|
+
- `multipartUpload` uses Azure's block-blob model: parallel `Put Block` (`?comp=block&blockid=<base64>`) calls followed by a single `Put Block List` (`?comp=blocklist`). There is no server-side upload session, so `abortMultipartUpload`, `listParts`, `listUploads` and `uploadPartCopy` are intentionally absent.
|
|
392
|
+
- Metadata passed to `multipartUpload` is applied on the final Put Block List, which is where Azure sets blob metadata.
|
|
393
|
+
- Browser uploads require the container's CORS rule to allow your origin and expose the `ETag` response header for `multipartUpload`.
|
|
394
|
+
- Use the shared-key (or SAS) flow only over HTTPS; the account key is a root credential — for anything user-facing prefer a server-generated SAS.
|
|
395
|
+
|
|
396
|
+
## Extension
|
|
397
|
+
|
|
398
|
+
Every operation is a factory over a `Protocol` — the extension point. A provider only has to implement two functions (`request`, `signUrl`) and fill in five constants; all operations (`put`, multipart, list, copy, …) then work unchanged. The built-in providers are the reference recipes: `src/cos/`, `src/obs/`, `src/aws/` (S3-shaped, each with its own signer) and `src/azure/` (non-S3-shaped — see the [Protocol](#protocol) section for the interface).
|
|
399
|
+
|
|
400
|
+
### Composing a custom provider
|
|
401
|
+
|
|
402
|
+
```js
|
|
403
|
+
import {
|
|
404
|
+
createPut,
|
|
405
|
+
createInitMultipartUpload,
|
|
406
|
+
createUploadPart,
|
|
407
|
+
createCompleteMultipartUpload,
|
|
408
|
+
createMultipartUpload,
|
|
409
|
+
createListUploads,
|
|
410
|
+
type Protocol,
|
|
411
|
+
} from 'tiny-oss/protocol';
|
|
412
|
+
|
|
413
|
+
const myProtocol = {
|
|
414
|
+
request(options, params) {
|
|
415
|
+
// 1. build the URL: host + '/' + objectName + sub-resource query
|
|
416
|
+
// 2. sign: compute your Authorization header from verb/date/headers/query
|
|
417
|
+
// 3. return getTransport()(url, { method, headers, data, timeout });
|
|
418
|
+
// (import { getTransport } from 'tiny-oss')
|
|
419
|
+
},
|
|
420
|
+
signUrl(options, objectName, urlOptions) { /* signed URL string */ },
|
|
421
|
+
metaPrefix: 'x-my-meta-',
|
|
422
|
+
copySourceHeader: 'x-my-copy-source',
|
|
423
|
+
copySourceRangeHeader: 'x-my-copy-source-range',
|
|
424
|
+
listUploadsMarkerKey: 'marker',
|
|
425
|
+
supportsSymlink: false,
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
const put = createPut(myProtocol);
|
|
429
|
+
const initMultipartUpload = createInitMultipartUpload(myProtocol);
|
|
430
|
+
const uploadPart = createUploadPart(myProtocol);
|
|
431
|
+
const completeMultipartUpload = createCompleteMultipartUpload(myProtocol);
|
|
432
|
+
const multipartUpload = createMultipartUpload(myProtocol, {
|
|
433
|
+
initMultipartUpload,
|
|
434
|
+
uploadPart,
|
|
435
|
+
completeMultipartUpload,
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
export { put, multipartUpload, signatureUrl: myProtocol.signUrl };
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Contributing a provider to the repo
|
|
442
|
+
|
|
443
|
+
Follow the `src/aws/` layout: `src/<provider>/{signature,host,request,signatureUrl,index}.ts`, then add the Vite build (`vite.<provider>.config.ts`), the `package.json` `exports` entry and `build:types:<provider>`. Signing must match the official SDK — the tests in `test/cos-signature.spec.ts`, `test/obs-signature.spec.ts` and `test/aws-signature.spec.ts` pin each signer against its official SDK as an oracle.
|
|
444
|
+
|
|
445
|
+
If the target storage's multipart API is not S3-shaped (e.g. Azure's block blobs), don't force it through `createInitMultipartUpload`/`createUploadPart`/`createCompleteMultipartUpload`: write provider-specific primitives with the same signatures and inject them via `createMultipartUpload` (see `src/azure/multipart.ts`). Operations that have no counterpart — like `listUploads` for Azure — are simply omitted from the entry.
|
|
446
|
+
|
|
447
|
+
## API
|
|
448
|
+
|
|
449
|
+
### options
|
|
450
|
+
|
|
451
|
+
The first argument of every operation. Only `accessKeyId` and `accessKeySecret` are required; the rest are optional:
|
|
452
|
+
|
|
453
|
+
```ts
|
|
454
|
+
interface Options {
|
|
455
|
+
accessKeyId: string; // Aliyun AccessKeyId
|
|
456
|
+
accessKeySecret: string; // Aliyun AccessKeySecret
|
|
457
|
+
stsToken?: string; // temporary credentials (recommended in browser)
|
|
458
|
+
bucket?: string; // the bucket to access
|
|
459
|
+
endpoint?: string; // the region domain; takes priority over region
|
|
460
|
+
region?: string; // the bucket's data region, default is 'oss-cn-hangzhou'
|
|
461
|
+
internal?: boolean; // access OSS over Aliyun's internal network, default is false
|
|
462
|
+
secure?: boolean; // use HTTPS (true) or HTTP (false), default is false
|
|
463
|
+
timeout?: string | number; // instance-level timeout for all operations, default is 60s
|
|
464
|
+
cname?: boolean; // use a custom domain name
|
|
465
|
+
pathStyle?: boolean; // S3-style path addressing (bucket in the URL path); required for S3-compatible endpoints such as MinIO and Cloudflare R2
|
|
466
|
+
}
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### put(options, objectName, blob, putOptions)
|
|
93
470
|
|
|
94
471
|
Upload the blob.
|
|
95
472
|
|
|
473
|
+
```ts
|
|
474
|
+
put(
|
|
475
|
+
options: Options,
|
|
476
|
+
objectName: string,
|
|
477
|
+
blob: BlobLike | string, // BlobLike = Blob | ArrayBuffer | Uint8Array
|
|
478
|
+
putOptions?: PutOptions // { onprogress?: (e: Progress) => any }
|
|
479
|
+
): Promise<any>
|
|
480
|
+
```
|
|
481
|
+
|
|
96
482
|
#### Arguments
|
|
97
483
|
|
|
98
|
-
* **
|
|
99
|
-
* **
|
|
100
|
-
* **
|
|
101
|
-
|
|
484
|
+
* **options**: `Options` — the client options, see above.
|
|
485
|
+
* **objectName**: `string` — the object name.
|
|
486
|
+
* **blob**: `BlobLike | string` — the object to be uploaded (`BlobLike = Blob | ArrayBuffer | Uint8Array`).
|
|
487
|
+
* **putOptions?**: `PutOptions` — optional upload options.
|
|
488
|
+
+ **onprogress?**: `(e: Progress) => any` — the upload progress event listener receiving a [progress event](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/progress_event) object as a parameter.
|
|
102
489
|
|
|
103
490
|
#### Return
|
|
104
491
|
|
|
105
|
-
*
|
|
492
|
+
* `Promise<any>`
|
|
106
493
|
|
|
107
|
-
### putSymlink(objectName, targetObjectName)
|
|
494
|
+
### putSymlink(options, objectName, targetObjectName)
|
|
108
495
|
|
|
109
496
|
Create a symlink.
|
|
110
497
|
|
|
498
|
+
```ts
|
|
499
|
+
putSymlink(
|
|
500
|
+
options: Options,
|
|
501
|
+
objectName: string,
|
|
502
|
+
targetObjectName: string
|
|
503
|
+
): Promise<any>
|
|
504
|
+
```
|
|
505
|
+
|
|
111
506
|
#### Arguments
|
|
112
507
|
|
|
113
|
-
* **
|
|
114
|
-
* **
|
|
508
|
+
* **options**: `Options` — the client options, see above.
|
|
509
|
+
* **objectName**: `string` — the symlink object name.
|
|
510
|
+
* **targetObjectName**: `string` — the target object name.
|
|
115
511
|
|
|
116
512
|
#### Return
|
|
117
513
|
|
|
118
|
-
*
|
|
514
|
+
* `Promise<any>`
|
|
119
515
|
|
|
120
|
-
### signatureUrl(objectName,
|
|
516
|
+
### signatureUrl(options, objectName, urlOptions)
|
|
121
517
|
|
|
122
518
|
Get a signature url to download the file.
|
|
123
519
|
|
|
520
|
+
```ts
|
|
521
|
+
signatureUrl(
|
|
522
|
+
options: Options,
|
|
523
|
+
objectName: string,
|
|
524
|
+
urlOptions?: SignatureUrlOptions // { expires?: number; method?: HTTPMethods; response?: ResponseHeaderType }
|
|
525
|
+
): string
|
|
526
|
+
```
|
|
527
|
+
|
|
124
528
|
#### Arguments
|
|
125
529
|
|
|
126
|
-
* **
|
|
127
|
-
* **
|
|
128
|
-
|
|
530
|
+
* **options**: `Options` — the client options, see above.
|
|
531
|
+
* **objectName**: `string` — the object name.
|
|
532
|
+
* **urlOptions?**: `SignatureUrlOptions` — optional signature options.
|
|
533
|
+
+ **expires?**: `number` — the url expiry (unit: seconds), default is 1800.
|
|
534
|
+
+ **method?**: `HTTPMethods` — the HTTP method, default is `'GET'`.
|
|
535
|
+
+ **response?**: `ResponseHeaderType` — response headers for download.
|
|
129
536
|
|
|
130
537
|
#### Return
|
|
131
538
|
|
|
132
|
-
*
|
|
539
|
+
* `string`
|
|
133
540
|
|
|
134
541
|
## LICENSE
|
|
135
542
|
|