Skip to content

Instantly share code, notes, and snippets.

@mandaputtra
Created July 26, 2023 01:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mandaputtra/aa9b94e2c67688e5e9c080a546c99334 to your computer and use it in GitHub Desktop.
Save mandaputtra/aa9b94e2c67688e5e9c080a546c99334 to your computer and use it in GitHub Desktop.
Download with Content-Range in AWS S3 Bucket

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);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment