Skip to content

Commit 3b150ce

Browse files
committed
add POC
1 parent 4970c94 commit 3b150ce

File tree

2 files changed

+114
-9
lines changed

2 files changed

+114
-9
lines changed

packages/react-storage/src/components/StorageBrowser/actions/handlers/download.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ function downloadFromUrl(fileName: string, url: string) {
3838
document.body.removeChild(a);
3939
}
4040

41-
export const downloadHandler: DownloadHandler = ({ config, data }) => {
41+
export const downloadHandler: DownloadHandler = ({ config, data }): DownloadHandlerOutput => {
4242
const { accountId, credentials, customEndpoint } = config;
4343
const { key } = data;
4444

@@ -53,14 +53,14 @@ export const downloadHandler: DownloadHandler = ({ config, data }) => {
5353
expectedBucketOwner: accountId,
5454
},
5555
})
56-
.then(({ url }) => {
57-
downloadFromUrl(key, url.toString());
58-
return { status: 'COMPLETE' as const, value: { url } };
59-
})
60-
.catch((error: Error) => {
61-
const { message } = error;
62-
return { error, message, status: 'FAILED' as const };
63-
});
56+
.then(({ url }) => {
57+
downloadFromUrl(key, url.toString());
58+
return { status: 'COMPLETE' as const, value: { url } };
59+
})
60+
.catch((error: Error) => {
61+
const { message } = error;
62+
return { error, message, status: 'FAILED' as const };
63+
});
6464

6565
return { result };
6666
};
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import {
2+
DownloadHandlerInput,
3+
DownloadHandlerOutput,
4+
} from "@aws-amplify/ui-react-storage/browser";
5+
import { getUrl } from "@aws-amplify/storage/internals";
6+
import {
7+
ZipWriterAddDataOptions,
8+
ZipWriter,
9+
BlobWriter,
10+
BlobReader,
11+
} from "@zip.js/zip.js";
12+
13+
const model = (() => {
14+
let zipWriter: ZipWriter<Blob> | null;
15+
return {
16+
addFile(file: Blob, name: string, options: ZipWriterAddDataOptions) {
17+
if (!zipWriter) {
18+
zipWriter = new ZipWriter(new BlobWriter("application/zip"), {
19+
bufferedWrite: true,
20+
});
21+
}
22+
return zipWriter.add(name, new BlobReader(file), options);
23+
},
24+
async getBlobURL() {
25+
if (zipWriter) {
26+
const blobURL = URL.createObjectURL(await zipWriter.close());
27+
zipWriter = null;
28+
return blobURL;
29+
} else {
30+
throw new Error("Zip file closed");
31+
}
32+
},
33+
};
34+
})();
35+
36+
const constructBucket = ({
37+
bucket: bucketName,
38+
region,
39+
}: DownloadHandlerInput["config"]) => ({ bucketName, region });
40+
41+
const download = async ({ config, data: { key } }: DownloadHandlerInput) => {
42+
const { customEndpoint, credentials, accountId } = config;
43+
const { url } = await getUrl({
44+
path: key,
45+
options: {
46+
bucket: constructBucket(config),
47+
customEndpoint,
48+
locationCredentialsProvider: credentials,
49+
validateObjectExistence: true,
50+
contentDisposition: "attachment",
51+
expectedBucketOwner: accountId,
52+
},
53+
});
54+
const response = await fetch(url, { mode: "cors" });
55+
const blob = await response.blob();
56+
const [filename] = key.split("/").reverse();
57+
await model.addFile(blob, filename, {});
58+
};
59+
60+
const customDownloadHandler = (() => {
61+
const q = new Set<string>();
62+
let timer: ReturnType<typeof setTimeout>;
63+
return (input: DownloadHandlerInput): DownloadHandlerOutput => {
64+
const {
65+
data: { key },
66+
} = input;
67+
const [, folder] = key.split("/").reverse();
68+
q.add(key);
69+
const result = download(input)
70+
.then(() => {
71+
q.delete(key);
72+
return {
73+
status: "COMPLETE",
74+
};
75+
})
76+
.catch((e) => {
77+
const error = e as Error;
78+
q.delete(key);
79+
return {
80+
status: "FAILED",
81+
message: error.message,
82+
error,
83+
};
84+
})
85+
.finally(() => {
86+
if (timer) clearTimeout(timer);
87+
timer = setTimeout(() => {
88+
if (q.size === 0) {
89+
model.getBlobURL().then((blobURL) => {
90+
if (blobURL) {
91+
const anchor = document.createElement("a");
92+
const clickEvent = new MouseEvent("click");
93+
anchor.href = blobURL;
94+
anchor.download = `${folder || "archive"}.zip`;
95+
anchor.dispatchEvent(clickEvent);
96+
}
97+
});
98+
}
99+
}, 250);
100+
});
101+
return { result: result as DownloadHandlerOutput["result"] };
102+
};
103+
})();
104+
105+
export { customDownloadHandler };

0 commit comments

Comments
 (0)