How to upload files from browser without using base64 encoding?

Viewed 920

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)
0 Answers
Related