How do I send an array of files using xhr2 and FormData? (Java + Spring)

喜欢而已 提交于 2020-06-28 08:20:08

问题


I'm using <input type="file" multiple /> to upload a list of files. This works fine as is, but I want the ability to remove individual files before upload, so I'm storing the FileList in a separate object and routing it through xhr. However, it doesn't work.

The form looks like this:

<form:form commandName="documentsBean" enctype="multipart/form-data">
    <input type="hidden" name="submittedFormAction" value="attachDocumentSave"/>
    <input type="file" name="files" id="attachFiles" multiple/>
    <button type="submit" id="attachButton" onclick="return buildForm(this.form);">Attach</button>
</form:form>

Here's the function that handles it (working version):

function buildForm(form){
    var formData = new FormData(form);
    formData.append('testString', "foobar");

    var xhr = new XMLHttpRequest();
    xhr.open('POST', form.action, true);
    xhr.send(formData);

    return false;
}

And the non-working version, where I try to stick the files into the formData manually:

function buildForm(form){
    var files = document.getElementById('attachFiles').files;

    // var tempfiles = [];
    // for(var i=0; i<files.length; i++){
    //     tempfiles[i]=files[i];
    // }

    var formData = new FormData();
    formData.append('submittedFormAction', "attachDocumentSave");
    formData.append('files', files);  // still broken with formData.append('files', tempfiles);
    formData.append('testString', "foobar");

    var xhr = new XMLHttpRequest();
    xhr.open('POST', form.action, true);
    xhr.send(formData);

    return false;
}

The bean:

public class DocumentsBean
{
    private List<MultipartFile> files = Arrays.asList();
    private String testString = "";

    public List<MultipartFile> getFiles(){
        return files;
    }
    public void setFiles(List<MultipartFile> files){
        this.files = files;
    }
    public String getTestString(){
        return testString;
    }
    public void setTestString(String testString){
        this.testString = testString;
    }
}

And the controller:

@RequestMapping( method = RequestMethod.POST, params = { "submittedFormAction=attachDocumentSave" })
public ModelAndView attachDocumentSave(HttpServletRequest request, @ModelAttribute("documentsBean") DocumentsBean documentsBean, BindingResult errors) throws Exception
{
    // Drilling into documentsBean here with the working version shows:
    //
    //     files= LinkedList<E>  (id=78)
    //         first= LinkedList$Node<E>  (id=94)
    //         last= LinkedList$Node<E>  (id=96)
    //         modCount= 3
    //         size= 3
    //     testString= "foobar" (id=84)
    //
    // and it successfully uploads the 3 files.

    // Drilling into documentsBean here with the non-working version shows:
    //
    //     files= Arrays$ArrayList<E>  (id=116)
    //         a= MultipartFile[0]  (id=121)
    //         modCount= 0
    //     testString= "foobar" (id=119)
    //
    // and it does not upload the files.
}

How can I make files correctly append to formData?


回答1:


In order for Spring to map items in a request to a list, you need to provide the same name (in the FormData.append calls) for each item when appending to the form data. This allows Spring to effectively see the request as name=value1&name=value2&name=value3 (but obviously in the form of form data). When Spring sees the same key ("name") multiple times, it can map the values into a collection. Going with your example, the name "files" is needed because your DocumentsBean has named it that way. That means your JavaScript code should change to be something like this:

function buildForm(form) {
    var files, formData, i, j, xhr;

    files = document.getElementById('attachFiles').files;
    formData = new FormData();

    formData.append('submittedFormAction', "attachDocumentSave");
    for (i = 0, j = files.length; i < j; i++) {
        formData.append('files', files[i]);
    }
    formData.append('testString', "foobar");

    xhr = new XMLHttpRequest();
    xhr.open('POST', form.action, true);
    xhr.send(formData);

    return false;
}


来源:https://stackoverflow.com/questions/22482170/how-do-i-send-an-array-of-files-using-xhr2-and-formdata-java-spring

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!