Skip to content

Instantly share code, notes, and snippets.

@gpDA
Last active September 19, 2021 12:39
Show Gist options
  • Save gpDA/9a445732a1fa6910681c5b7f19134f02 to your computer and use it in GitHub Desktop.
Save gpDA/9a445732a1fa6910681c5b7f19134f02 to your computer and use it in GitHub Desktop.
// chunkUpload
// uniformChunkRequest
// partialChunkRequest
// chunkRequestHelper
// want to go over
// 1 - uniform & partial upload (why there are 2 different functions)
// 2 - use of `chunkRequestHelper` function to send headers & body (formData)
// 3 - chunkStar & chunkEnd - how it's being calculated `chunkStart + CHUNK_SIZE > fileClone.size`
async chunkUpload(directory: string, file: File,
totalBytesUploaded?: number,
permissionList?: Array<FSPermissions>,
onUploadProgress?: (e: any) => void,
cancelToken?: CancelToken): Promise<FSReport> {
const fileName = file.name;
// If there are totalBytesUploaded, divide by CHUNK_SIZE and * CHUNK_SIZE
// to start from chunk size(s) done before retry/resume upload
const chunkStart = totalBytesUploaded
? (Math.floor(totalBytesUploaded / CHUNK_SIZE) * CHUNK_SIZE)
: 0;
// If there are totalBytesUploaded, add CHUNK_SIZE to chunkStart calculation
// to get the next chunkEnd after chunk size(s) done before retry/resume upload
const chunkEnd = totalBytesUploaded
? ((Math.floor(chunkStart / CHUNK_SIZE) * CHUNK_SIZE) + CHUNK_SIZE)
: CHUNK_SIZE;
const path = `${directory}/${fileName}`;
const fileObj = {
path,
file, // <File> File
chunkStart,
chunkEnd,
};
// uniformChunkRequest request
return fs.uniformChunkRequest(fileObj,
permissionList,
onUploadProgress,
cancelToken);
}
// IF the file size left < CHUNK_SIZE;
// usually the very last request
async partialChunkRequest(chunkRequestObj: ChunkRequest,
permissionList?: Array<FSPermissions>,
onUploadProgress?: (e:any) => void,
cancelToken?: CancelToken): Promise<FSReport> {
const { url, formData, options } = this.chunkRequestHelper(chunkRequestObj,
permissionList, onUploadProgress, cancelToken);
return new Promise((resolve, reject) => {
// axios request
axios.put(url, formData, options).then((response) => {
if (response.status === 200) {
resolve(response.data);
}
}).catch(err => reject(err));
});
}
// recursive call
// Slice the file size and
// Upload the file with a CHUNK_SIZE;
async uniformChunkRequest(chunkRequestObj: ChunkRequest,
permissionList?: Array<FSPermissions>,
onUploadProgress?: (e: any) => void,
cancelToken?: CancelToken): Promise<FSReport> {
const {
path, file, chunkStart, chunkEnd,
} = chunkRequestObj;
const fileClone = file.slice();
// Less than CHUNK_SIZE left
if (chunkStart + CHUNK_SIZE > fileClone.size) {
return this.partialChunkRequest({
path,
file,
chunkStart,
chunkEnd: file.slice().size,
},
permissionList, onUploadProgress, cancelToken);
}
const { url, formData, options } = this.chunkRequestHelper(chunkRequestObj,
permissionList, onUploadProgress, cancelToken);
// axios request
await axios.put(url, formData, options);
const updateRequestParams = {
chunkStart: chunkEnd,
chunkEnd: chunkEnd + CHUNK_SIZE,
};
return this.uniformChunkRequest({
path,
file,
chunkStart: updateRequestParams.chunkStart,
chunkEnd: updateRequestParams.chunkEnd,
},
permissionList, onUploadProgress, cancelToken);
}
// helper
chunkRequestHelper({
path, file, chunkStart, chunkEnd,
}: ChunkRequest,
permissionList?: Array<FSPermissions>,
onUploadProgress?: (e: any) => void,
cancelToken?: CancelToken): chunkRequestHelper {
const uniqueId = path.split('/').join('');
const formData = new FormData();
const slicedPart = file.slice(chunkStart, chunkEnd);
const fileClone = file.slice();
const url = `${apiCarfs.url}/fs/${encodeURIComponent(encodeURIComponent(path))}`;
if (permissionList && permissionList.length) {
formData.set('permissions', JSON.stringify(permissionList));
} else {
formData.set('permissions', '[]');
}
formData.set('file', slicedPart);
const options = {
headers: {
'Content-Type': 'multipart/form-data',
'Content-Range': `bytes ${chunkStart}-${chunkEnd - 1}/${fileClone.size}`,
'car-meta-chunk-file-id': `${uniqueId}`,
},
onUploadProgress,
cancelToken,
};
return {
url,
formData,
options,
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment