I have existing upload code that lets the user select a file using the regular HTML input file selection dialog then uses HTML FileReader.readAsDataURL to get the file as a Base64 string and POST to the server where it is Base64 decoded and saved.
I have now been asked to handle very large files (a few hundred MB I think), and therefore to switch from using Base64 encoding as it will hammer the browser and the server. How do I do this with the least work possible, and/or what are my options here? Looks like FileReader has readAsArrayBuffer or readAsBinaryString (not on IE, but that's OK), but not sure how to adapt my code to use these.
I think this question is language/framework agnostic (as basically about what HTML/JS functions to use) but for what it's worth my front end is Angular and my backend Groovy/Grails (i.e. Java).
Client:
uploadMyFile(name: string):void {
let fr: FileReader = new FileReader();
// Set up the event handler for the FileReader, triggered once the user selected file has been loaded locally (e.g. from a local drive)
fr.onload = (e) => {
uploadArgs.fileContent = fr.result;
this.handleUploads.uploadTheFile(name, fr.result) // See code block below for uploadTheFile
.subscribe((response) => {
// Confirm upload
},
(reason) => {
// handle error
});
};
// Read the data in locally (e.g. from a local drive), this triggers the fr.onload() event defined above. (Read as Base64)
fr.readAsDataURL(this.fileToUpload);
}
also client:
uploadTheFile(name:string, content:any):Observable<MyUploadResult> {
const formData: FormData = new FormData();
formData.append('fileName', name);
formData.append('fileContent', content);
return this.http.post<MyUploadResult>("uploadURL", formData, this.httpUploadJSONOptions).pipe(
tap(),
catchError((err: HttpErrorResponse) => this.handleError(err)));
}
Server - does some validation, then decodes the content that was received as a base64 string, into a byte array, relevant bit of code:
// Remove Data-URL declaration "data:*/*;base64," from start of upload leaving just Base64-encoded file data:
String base64Str = cmd.fileContent.substring(cmd.fileContent.indexOf(",") + 1)
BASE64Decoder decoder = new BASE64Decoder()
byte[] decodedContent = decoder.decodeBuffer(base64Str)