Requirements:
- User may select multiple files using
<input type="file" multiple>
- Once files are selected, we want multiple http requests sent (one request per file) to upload the files to a web server, with a concurrency level
n
, meaningn
files can be uploaded simultaneously. - If one request fails, automatically retry it up to 3 times with a back off rate at 1.5
- Show progress bar/message somehow.
The js code for uploading the selected files:
/**
* For callers interested in only file uploading completed events, should provide 'completed' callback instead of 'next' callback.
*/
export function uploadFiles(
files: File[],
http: HttpClient,
urlFn: (file: File) => string,
progressUpdator: (progress: number) => void,
concurrency = 3
) {
return from(files).pipe(
mergeMap(x => {
const targetUrl = urlFn(x);
return http.put(targetUrl, x, {
reportProgress: true,
observe: 'events',
}).pipe(
retryWhen(errors => errors.pipe(
take(3),
switchMap((err, idx) => {
// retry with backoff rate 2
return timer(500 * Math.pow(2, idx))
}))
),
tap(evt => {
// notify that upload progress has changed
if (evt.type === HttpEventType.UploadProgress) {
progressUpdator(evt.loaded / (evt.total/100.0))
}
})
)
}, concurrency)
);
}
More interestingly, rxjs's .NET implementation rxNet, can be used similarly in .NET MAUI, Xamarin and even the dinosaur Windows Forms. Please stay tuned and I will publish a new article for that.