Need to enable in the S3 Bucket console
"ExposeHeaders": [
"ETag",
"Content-Length",
"Range",
"Content-Range"
]| // import {} from 'native-file-system-adapter' | |
| const PRESIGNED_URLS = | |
| "https://development-nearbysky-user-contents.s3.ap-southeast-2.amazonaws.com/64bf77f4e5811400230607eb/PPGWDU_4k_video.mp4?response-content-disposition=inline&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEKH%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDmFwLXNvdXRoZWFzdC0xIkgwRgIhAIn1H2hme5sPvRyU1qDn4ram8FbL5jhigz9ChRoqOKDaAiEA0xqgYXoEnliamxQM8Ju7CX8vmRFJrpnHHh9f1LvrBvEqhQMIOhAEGgw3NjU4OTU2NDU1MDAiDPjJgKVLV08uFhvFzCriAswqxz3jjdwmQm59swDLYwyGFpptsdIJ%2FlygtmnJ7zH0gMmVsQxfu4Yl0DcfqHrjCEao9wtdqTvv0zdpUG4Lg3NcxB%2F%2F0MHXbtJjEl7xNPvCDzIZZDzTOmEjs0ucuyg3%2FqH3MUFFwl8ZEcyVWBE%2FqVeyL2Gg%2BlEzH4%2FtU3NSoVEk4e54x%2BWwPtUpCxs8IwYjg25qP53zl2tBpPgIy4meLhbI6rH57uHkpi%2FUx2%2Fjt1rButeBSG4FlVgMaHBTFoBgMN2%2FEvrFyPinSWdutp3%2FLlJa%2BMEdd7XhVLP67me%2BS7EatP60EG9LAZn%2FD5NYGpQen9BeIJ1nmwxFRHfBegvPpDIyax97GUVYNvS%2BgI9WluVHQZ47GjhAsmOQEhuicCdXAxdBxquP9RZaSSO6%2FViTzlw5w3GDNqml5bw4kYuED7hoBWYCZFkx0ugT9r%2BovRSJfwQXAAWGopG2hFSHGp4EUyzXezDE3oGmBjqyAj02CzkZ0q9wtLGy8DaMJAL69%2F%2F5z1wcAaCVvT6aDYlb50tyCJ%2BnGaWGtjaLnnst7buNAv7BErJkkeGkTMcHipcPgZPHjGpC1BW7F4V77XPxs82mucT%2Fc5CUYSJfADPPei6%2BG79UUnR9sYJW7DDJIoRKRSrfcIHhZTHuevoxHdNz%2BREjCJz9mbKhiQFh0vd34FTFHygqydUFtpuWi%2FLZ6I%2FaRH0m8ZDa9pDSdwTYXIB5OpJuToA9LkJYWvzIsPcYoIumKYdVvCDrKYzlnJeAqjWmhEGsP3NJFeF6Dqtm0S6762YRkcJmYFQ2zqVoMUJDdU13covJjxJ%2Fzl5ZqHvWAEx%2BDHQu8OMoT1vHqu%2BFyZpctTpaO7N6hQ6NEpQ5cR%2Bw2BlvYSZmrpNjoSqS5epjO%2B9Nkw%3D%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20230726T005838Z&X-Amz-SignedHeaders=host&X-Amz-Expires=43200&X-Amz-Credential=ASIA3EUXQDE6KGVO4IL6%2F20230726%2Fap-southeast-2%2Fs3%2Faws4_request&X-Amz-Signature=444b4abf5f2e317df3db429fb7a4b29e8d64350c66dcbcfa1b55359521a594a2"; | |
| const ONE_MB = 1024 * 1024; | |
| async function fetchWithRange(url: string, start: number, end: number) { | |
| const res = await fetch(url, { | |
| headers: { | |
| range: `bytes=${start}-${end}`, | |
| }, | |
| }); | |
| return res; | |
| } | |
| function getRangeAndLength(contentRange: string | null) { | |
| console.log(contentRange, "Content Range"); | |
| if (contentRange) { | |
| const [range, length] = contentRange.split("/"); | |
| const [start, end] = range.split("-"); | |
| return { | |
| start: parseInt(start), | |
| end: parseInt(end), | |
| length: parseInt(length), | |
| }; | |
| } | |
| throw Error("No content range in headers!"); | |
| } | |
| type RangeAndLength = { | |
| start: number; | |
| end: number; | |
| length: number; | |
| }; | |
| export const isComplete = ({ end, length }: RangeAndLength) => | |
| end === length - 1; | |
| async function downloadInChunks(url: string) { | |
| let rangeAndLength = { start: -1, end: -1, length: -1 }; | |
| while (!isComplete(rangeAndLength)) { | |
| const { end } = rangeAndLength; | |
| const nextRange = { start: end + 1, end: end + ONE_MB }; | |
| console.log(`Downloading bytes ${nextRange.start} to ${nextRange.end}`); | |
| const res = await fetchWithRange(url, nextRange.start, nextRange.end); | |
| if (res.ok) { | |
| rangeAndLength = getRangeAndLength(res.headers.get("Content-Range")); | |
| } else { | |
| throw Error(await res.json()); | |
| } | |
| } | |
| } | |
| await downloadInChunks(PRESIGNED_URLS); |