Skip to content

Commit b45263b

Browse files
committed
docs: add azure blob uploader example
1 parent 7693ad3 commit b45263b

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

uploader-examples/blob-uploader .ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { Uploader } from 'ngx-uploadx';
2+
3+
/**
4+
* Azure Blob Storage support
5+
* @example
6+
* options: UploadxOptions = {
7+
* allowedTypes: 'image/*,video/*',
8+
* maxChunkSize: 512 * 1024 * 1024,
9+
* endpoint: `[signedURL]`,
10+
* uploaderClass: BlobUploader
11+
* };
12+
*/
13+
14+
const BLOB_API_VERSION = '2022-11-02';
15+
16+
export class BlobUploader extends Uploader {
17+
blockList: string[] = [];
18+
override async getFileUrl(): Promise<string> {
19+
const oUrl = new URL(this.endpoint);
20+
oUrl.pathname = [oUrl.pathname, this.file.name].join('/');
21+
const url = oUrl.toString();
22+
return url;
23+
}
24+
25+
override async sendFileContent(): Promise<number | undefined> {
26+
const { body, start, end } = this.getChunk();
27+
const blockId = btoa(this.uploadId + String(start).padStart(15, '0'));
28+
const url = this.url + `&comp=block&blockid=${encodeURIComponent(blockId)}`;
29+
const headers = commonHeaders();
30+
await this.request({ method: 'PUT', headers, url, body });
31+
this.blockList.push(blockId);
32+
if (end === this.size) {
33+
await this.finish();
34+
}
35+
return this.responseStatus > 201 ? start : end;
36+
}
37+
38+
async finish() {
39+
const blocks = this.blockList.map(blockId => `<Latest>${blockId}</Latest>`).join('');
40+
const body = `<?xml version="1.0" encoding="utf-8"?><BlockList>${blocks}</BlockList>`;
41+
const url = `${this.url}&comp=blocklist`;
42+
const headers = { ...commonHeaders(), 'Content-Type': 'text/xml; charset=UTF-8' };
43+
await this.request({ method: 'PUT', headers, url, body });
44+
return this.size;
45+
}
46+
47+
override abort(): void {} // FIXME: Azurite does not support blob upload interrupts?!
48+
49+
override async getOffset(): Promise<number | undefined> {
50+
const url = this.url + `&comp=blocklist&blocklisttype=all`;
51+
const headers = commonHeaders();
52+
try {
53+
await this.request({ headers, url });
54+
const parser = new DOMParser();
55+
const xmlDoc = parser.parseFromString(this.response, 'text/xml');
56+
const blocks = xmlDoc
57+
.getElementsByTagName('UncommittedBlocks')[0]
58+
.getElementsByTagName('Block');
59+
const sizes = Array.from(blocks).map(
60+
el => +(el.getElementsByTagName('Size')[0]?.textContent ?? '0')
61+
);
62+
return sizes.reduce((acc, v) => acc + v, 0);
63+
} catch {}
64+
return this.offset || 0;
65+
}
66+
}
67+
68+
function commonHeaders() {
69+
return {
70+
'x-ms-version': BLOB_API_VERSION,
71+
'x-ms-date': new Date().toISOString()
72+
};
73+
}

0 commit comments

Comments
 (0)