multipart/form-data binding pour ModelAttribute échoue si le fichier en plusieurs parties paramètre est null
J'ai un contrôleur mappé pour le traitement des fichiers téléchargés
Contrôleur
@RequestMapping(value = "/careers/pursue", method = RequestMethod.POST)
public Callable<String> pursue(
final @RequestParam("g-recaptcha-response") String captchaResponse,
final @RequestParam("file") MultipartFile file,
final @ModelAttribute("jobapplication") @Valid JobApplication application, final BindingResult bindingResult,
final Model model)
forme
<form name="jobsForm" id="jobsForm" novalidate="novalidate" action="#" th:action="@{/careers/pursue}"
th:object="${jobapplication}" method="post" enctype="multipart/form-data">
<div class="control-group form-group">
<div class="controls">
<label>First Name:</label>
<input type="text" class="form-control" id="firstName" th:field="*{firstName}" required="required" data-validation-required-message="Please enter your name." />
<p class="help-block"></p>
</div>
</div>
<div class="control-group form-group">
<div class="controls">
<label>Last Name:</label>
<input type="text" class="form-control" id="lastName" th:field="*{lastName}" required="required" data-validation-required-message="Please enter your name." />
<p class="help-block"></p>
</div>
</div>
<div class="control-group form-group">
<div class="controls">
<label>Phone Number:</label>
<input type="tel" class="form-control" id="phone" th:field="*{phone}" required="required" data-validation-required-message="Please enter your phone number." />
</div>
</div>
<div class="control-group form-group">
<div class="controls">
<label>Email Address:</label>
<input type="email" class="form-control" id="email" th:field="*{email}" required="required" data-validation-required-message="Please enter your email address."/>
</div>
</div>
<div class="control-group form-group">
<div class="controls">
<label>Role:</label>
<input type="email" class="form-control" id="role" th:field="*{role}" required="required" data-validation-required-message="Please enter your email address."/>
</div>
</div>
<div class=" control-group form-group">
<div class="g-recaptcha" data-sitekey="ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"></div>
</div>
<div class=" control-group form-group">
<span class="btn btn-primary btn-file">
Add your Resumé <input type="file" name="file" id="file" required="required"/>
</span>
</div>
<div id="success"></div>
<!-- For success/fail messages -->
<button type="submit" class="btn btn-primary">Apply!</button>
</form>
Maintenant, si une personne manque d'attacher un fichier à un formulaire avant de le soumettre,
-----------------------------749526091303082321866336941
Content-Disposition: form-data; name="firstName"
Anadi
-----------------------------749526091303082321866336941
Content-Disposition: form-data; name="lastName"
Misra
-----------------------------749526091303082321866336941
Content-Disposition: form-data; name="phone"
9845420420
-----------------------------749526091303082321866336941
Content-Disposition: form-data; name="email"
foo@bar.com
-----------------------------749526091303082321866336941
Content-Disposition: form-data; name="role"
open.project
-----------------------------749526091303082321866336941
Content-Disposition: form-data; name="g-recaptcha-response"
03AHJ_Vuv9i7WQ_4zCipfnyrLNl6467l_cZgGIhkdpLjS1M0YmWvwQMOWQeRcrAHFh8s3-jO13NQs7019lzI7UobwNeHKIhBmcLMiVGPk38Iy8BjrEi2glI4QGjE4VTvRhV_-WWYsmlzV_7PRPE5Y8L0NboPXYoG9JSabMOL8V958w74pOzkxabsoR4wouCSa0gzo0EbOsLiCWjd0MAvZiCcKJGdwIlMp0WIjxcufB-RfG2F0rwv65yrgL-By0bdMewkWULY_aRvC-FRSqOEM9X5Qg4gviA-cvc5IY2XnRtaUALOPlR_QbwjgUKl2mJEFNab6Pks3MlsivuEZFkba4isDFlrJ4jXwBBQ
-----------------------------749526091303082321866336941
Content-Disposition: form-data; name="file"; filename=""
Content-Type: application/octet-stream
-----------------------------749526091303082321866336941--
ou tente de soumettre sans valider le captcha, j'ai cette exception
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring4.processor.attr.SpringInputGeneralFieldAttrProcessor' (jobs:91)
....
....
Caused by: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'jobapplication' available as request attribute
at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:144)
at org.thymeleaf.spring4.util.FieldUtils.getBindStatusFromParsedExpression(FieldUtils.java:396)
at org.thymeleaf.spring4.util.FieldUtils.getBindStatus(FieldUtils.java:323)
at org.thymeleaf.spring4.util.FieldUtils.getBindStatus(FieldUtils.java:289)
at org.thymeleaf.spring4.processor.attr.AbstractSpringFieldAttrProcessor.processAttribute(AbstractSpringFieldAttrProcessor.java:98)
at org.thymeleaf.processor.attr.AbstractAttrProcessor.doProcess(AbstractAttrProcessor.java:87)
at org.thymeleaf.processor.AbstractProcessor.process(AbstractProcessor.java:212)
... 66 common frames omitted
Ce que j'attends, c'est que j'obtiens des valeurs vides pour le captcha et réponse de fichier et puis ma méthode de contrôleur doit être en mesure de le manipuler, et d'envoyer l'utilisateur vers le formulaire avec un message d'erreur spécifique. Il fonctionne comme sur des formes sans multipart de données, c'est à dire que je n'ai pas de liaison des erreurs, mais des valeurs null dans les arguments du contrôleur. Je vois ce problème uniquement quand j'utilise Multipart des données de Formulaire, la liaison va bien si toutes les données sont remplies, c'est à dire un utilisateur vérifie captcha, et attache un fichier.
Faire de ces paramètres en option ou à l'aide de RequestPart n'a pas aidé (j'avoue je n'ai vraiment pas obtenir ce qui est le but de RequestPart
annotation) Donc, en changeant le contrôleur (réflexe expérimentations ;-))
@RequestMapping(value = "/careers/pursue", method = RequestMethod.POST)
public Callable<String> pursue(
final @RequestPart(value = "g-recaptcha-response", required = false) String captchaResponse,
final @RequestPart(value = "file", required = false) MultipartFile file,
final @ModelAttribute("jobapplication") @Valid JobApplication application, final BindingResult bindingResult,
final Model model)
n'aide pas non plus. Dois-je prolonger StandardServletMultipartResolver ou est-il quelque chose à changer/réparer dans SpringInputGeneralFieldAttrProcessor, ou ai-je raté quelques petits détails ici?
Mise à jour
Ajout de la méthode du Contrôleur
@RequestMapping(value = "/careers/pursue", method = RequestMethod.POST)
public Callable<String> pursue(final @ModelAttribute("jobapplication") @Valid JobApplication application,
final BindingResult bindingResult, final Model model,
final @RequestParam(value = "g-recaptcha-response", required = false) String captchaResponse,
final @RequestPart(value = "file", required = false) MultipartFile file) {
return new Callable<String>() {
@Override
public String call() throws Exception {
try {
model.asMap().clear();
GoogleCaptchaResponseData response = captchaVerifier.isCaptchaResponseValid(captchaResponse).get();
model.addAttribute("recaptcha", response.isSuccess());
model.addAttribute("recaptchamessage", response.getErrorCodes());
if (response.isSuccess() && !file.isEmpty()) {
byte[] bytes = file.getBytes();
LOGGER.info("Found file of type {}", file.getOriginalFilename());
ByteArrayInputStream inputBytes = new ByteArrayInputStream(bytes);
mailApi.sendMail(mailApi.buildJobApplicationEmail(application, new BufferedInputStream(inputBytes)));
model.asMap().clear();
model.addAttribute("uploadsuccess", true);
model.addAttribute("resource_host", resourceHost);
model.addAttribute("jobapplication", new JobApplication());
}
} catch (InterruptedException | ExecutionException e) {
LOGGER.error(e.getMessage(), e);
model.asMap().clear();
model.addAttribute("jobapplication", application);
model.addAttribute("resource_host", resourceHost);
model.addAttribute("uploadsuccess", false);
}
return "jobs";
}
};
}
OriginalL'auteur Anadi Misra | 2015-02-27
Vous devez vous connecter pour publier un commentaire.
@RequestPart s'appuie sur HttpMessageConvertors et de type de contenu pour lier le multipart données à la méthode param, alors que @RequestParam s'appuie sur les convertisseurs de faire la conversion. Spring mvc fournit certains convertisseurs par défaut. Vous pouvez utiliser @RequestParam ou @RequestPart pour lier le fichier de données. La plupart des applications utilisent des communes de téléchargement de fichier pour le téléchargement de fichier et l'enregistrer
pour la partie multi de se résoudre. Lorsque cela est enregistré, le printemps de vérifier chaque demande pour la partie multi de données et l'utiliser pour résoudre cette méthode arg. consultez ici les
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-multipart
Il y a quelques éléments que vous pouvez essayer. Assurez-vous que vos deux captcha et fichier params sont facultatifs comme ci-dessous dans votre contrôleur. Je suis passé à @RequestParam pour captcha.
Espère que cette aide.
StandardServletMultipartResolver
se comporter d'une autre deCommonsMultipartResolver
?il peut aider ainsi. Il est configuré différemment. J'ai surtout utilisé communes. Qu'utilisez-vous?
Je suis sur le printemps de démarrage qui utilise apparemment
StandardServletMultipartResolver
en tant que par défaut multipart de résolution.changé à la syntaxe proposée par @minion et de configuration ajout de
CommonsMultipartResolver
, n'a pas aidé, obtiens toujours la même erreurJe vais avoir le même problème. S'il vous plaît laissez-moi savoir si vous les gars trouve des solutions de contournement.
OriginalL'auteur minion
@RequestMapping
n'est pas mappé sur le même chemin que pour la forme@RequestParam
@RequestParam
ne passe pas un null avis je suis à la recherche d'length() == 0
etfile.isEmpty()
Aussi, vous voudrez peut-être prendre un coup d'oeil à la guide de ressort pour le fichier de téléchargement
Contrôleur
Forme
L'erreur que vous avez posté est sur le jobapplication de haricots à la place du fichier. Est jobapplication bean null? Est le captcha et fichier le cadre de jobapplication ?
si vous regardez le multipart de données que j'ai posté, j'ai cette erreur pour
jobapplication
bean sifile
oug-response-captcha
est vide. C'est déconcertant de moi. captcha param est joint à la demande par google captcha, de fichiers et de captcha ne sont pas une partie de lajobapplication
beanJ'ai ajouté la forme complète du code html de trop.
J'ai un fichier dans le cadre de haricot. 'modelattribute' cartographie échoue lorsque j'essaie d'envoyer le formulaire sans sélectionner de fichier. Avez-vous trouvez une solution?
OriginalL'auteur ndrone