Converting <input type=file> contents to Base64 and sending to Spring method expecting MultiPartFile

321 views Asked by At

Because of server issues I need to convert the contents of a file upload to Base64 before it gets submitted to the server.

I've managed the JS side of things using reader.readAsDataURL to get the contents into Base64 in a local JS variable. I've then tried creating a new FormData and setting the base64 variable there - it replaces the name of the but then it also replaces the type - it's no longer a but just binary data - so when I send this to the server - I'm getting Spring error typeMismatch.org.springframework.web.multipart.MultipartFile

Basically - any thoughts how to convert file contents to Base64 (done that ok) but send to existing JAVA method with Spring MultiPartFile?

i.e. without me rewriting and adding extra fields in the FormData for file name and size etc (the stuff I'd get using the MultipartFile on the server end). JS: (error handling removed)

var input = $(".actualFileInput");
var files = null;
// File data
if (input[0].files.length > 0) {
    files = input[0].files;
}
var file = files[0], reader = new FileReader();
            
reader.onloadend = function () {
    var b64 = reader.result.replace(/^data:.+;base64,/, '');
    var name = input.attr('name');
    input.attr('name', '');
                
    var newFormData = new FormData(form);   // New form with all data from the existing one
    newFormData.set('uploadFile',b64);  // replace with the base64 value of the selected file
    var request = new XMLHttpRequest();
                
    request.onreadystatechange = function () {
        request.open(form.method, form.action, true);
        request.onload = function() {
            var url = window.location;
            input.attr('name', name);   
            request.send(newFormData);
                
    };
reader.readAsDataURL(file);

The Java at the server end:

@RequestMapping(method = RequestMethod.POST, params = "upload")
public String upload(@ModelAttribute("uploadDocument") UploadDocument document, BindingResult result,
        ModelMap model, HttpServletRequest request, SessionStatus status) throws Exception {

UploadDocument is:

public class UploadDocument implements Serializable {

private static final long serialVersionUID = -3534003705995293025L;

// File upload work area
private MultipartFile   uploadFile = null;
private String          fileComment = null;
private Integer         fileTypeId = null;
... (other fields in the <form>)

All the JAVA stuff works fine if I just submit the form. But in JS reading the file contents as Base64 then sending as a field doesnt get translated to MultiPartFile. Change to byte[] and add new fields for the file metadata myself? Or is there some trick I'm missing.

Thanks folks.

1

There are 1 answers

0
RobM On

The way to make this JS variable send to a Spring MultiPartFile is:

newFormData.set('uploadFile',new Blob([b64]),files[0].name); // replace with the base64 value of the selected file

i.e. make it a blob, and 3rd arg is the file name the user selected in . This now sends the base64 value of the file contents.