web-dev-qa-db-fra.com

Vide la liste <MultipartFile> lors de la tentative de téléchargement de nombreux fichiers au printemps avec ng-file-upload

J'ai la méthode de contrôleur suivante pour télécharger plusieurs fichiers à la fois, inspirée par cet article de blog et les réponses à cette question aussi:

@RequestMapping(value = "/{user}/attachment", method = RequestMethod.POST)
@PreAuthorize(...)
public void upload(@PathVariable User user, 
                   @RequestParam("file") List<MultipartFile> files) {
  // handle files
}

Cependant, la liste des fichiers est toujours vide même si la requête les contient.

Si j'ajoute le troisième paramètre MultipartRequest à la méthode:

public void upload(@PathVariable User user, 
                   @RequestParam("file") List<MultipartFile> files,
                   MultipartRequest request)

Je peux voir qu'il contient mes fichiers téléchargés correctement:

request contents

Quelle pourrait être la raison de List<MultipartFile> vide?

J'utilise ng-file-upload pour soumettre les fichiers, mais je ne pense pas que cela soit lié au problème. Printemps 4.2.4.

12
fracz

Le problème était que ng-file-upload par défaut soumet un tableau de fichiers utilisant les noms file[0], file[1], etc. Il est configurable avec la valeur arrayKey en utilisant le service Upload. Le fait de le définir sur chaîne vide force l'envoi des fichiers sous la même clé file, qui est correctement résolue avec Spring et dont la fonction @RequestParam("file") List<MultipartFile> contient tous les fichiers soumis.

Upload.upload({url: url, data: {file: arrayOfFiles}, arrayKey: ''})
19
fracz

Essayez d'utiliser @ModelAttribute comme ceci:

    @RequestMapping(value = "/{user}/attachment", method = RequestMethod.POST)
    @PreAuthorize(...) 
    public void upload(@PathVariable User user,@ModelAttribute("uploadFile") FileUpload uploadFile) throws IllegalStateException, IOException {

    List<MultipartFile> files = uploadFile.getFiles();
    ...

Et créez une classe comme:

     public class FileUpload {
     private List<MultipartFile> files;
     public List<MultipartFile> getFiles() {
        return files;
     }

    public void setFiles(List<MultipartFile> files) {
       this.files= files;
      }
   }
4
Abdelhak

Cela fonctionne pour moi, envoyer de gros objets 'email' avec plusieurs pièces jointes de l'interface utilisateur au back-end

Angular

sendEmailWithAttachments(taskId: string, template: string, email: any, modelConfig: any, files: any[]) {
    let formData = new FormData();
    formData.append('form', new Blob([JSON.stringify(email)], {type: 'application/json'}));
    files.forEach(file  => {
        formData.append('files', file);
    });

    return this.$http({
        method: 'POST',
        data: formData,
        url: this.baseUrl + '/' + taskId + '/email-with-attachment?template=' + template,
        headers: {
            'Content-Type': undefined
        },
        responseType: 'arraybuffer'
    });
}

Java Spring

@RequestMapping(value = "{taskId}/email-with-attachment", method = RequestMethod.POST, consumes = MULTIPART_FORM_DATA_VALUE)
public void sendEmailWithAttachment(
        @PathVariable String taskId,
        @RequestParam String template,
        @RequestParam("form") MultipartFile form,
        @RequestParam("files") List<MultipartFile> files) throws IOException {
    Map<String, String> parameters = new ObjectMapper().readValue(form.getInputStream(), HashMap.class);

    System.out.println("taskId", taskId);
    System.out.println("template", template);
    System.out.println("files", files);
    System.out.println("parameters", parameters);
}
0
Dmitri Algazin

Je pense que de la manière dont vous avez envoyé les données de face, il ne peut pas bound avec Java.util.List. Si vous créez une donnée JSON en tant que demande et que vous annotez votre liste avec @RequestBody, comme suit:

@RequestMapping(value = "/{user}/attachment", method = RequestMethod.POST)
@PreAuthorize(...)
public void upload(@PathVariable User user, 
                   @RequestBody List<MultipartFile> files) {
  // handle files
}

ça devrait marcher. Quelques infos ici .

0
alexandrum