Reputation: 366
I'm working with spring Data-Jpa using spring boot. I have a multipart form to upload file to the database with additional fields such as ( firstName, lastName, email,resume etc.) But I keep getting this error message for converting multipart file into required byte[] type. How can I convert the pdf file from multipart file to byte[] type?
Here is myControllerClass
@RequestMapping(value = "/jobs/applyJob/{id}", method = RequestMethod.POST)
public String handleFormSubmit(@PathVariable Long id, @ModelAttribute @Valid Candidate candidate,
BindingResult bindingResult, @RequestParam("resume") MultipartFile file,
RedirectAttributes redirectAttributes) {
Job job = jobService.findJob(id);
candidate.setJob(job);
if (file.isEmpty()) {
return null;
}
try {
byte[] content = file.getBytes();
Path path = Paths.get(UPLOAD_FOLDER + file.getOriginalFilename());
Files.write(path, content);
} catch (IOException e) {
e.printStackTrace();
}
if (bindingResult.hasErrors()) {
return "applyJob";
}
redirectAttributes.addFlashAttribute("message", "Job applied !");
return "redirect:/jobs";
}
My entity :
@Entity
@Table(name = "candidates")
public class Candidate {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotEmpty
@Column(name = "first_name", length = 50)
private String firstName;
@NotEmpty
@Column(name = "last_name", length = 50)
private String lastName;
@NotEmpty
@Column(name = "email", length = 100)
private String email;
@NotEmpty
@Column(name = "phone", length = 15)
private String phone;
@NotEmpty
@Column(name = "address", length = 255)
private String address;
@NotEmpty
@Column(name = "thoughts_on_job", length = 255)
private String thoughtsOnJob;
@NotEmpty
@Column(name = "resume")
@Lob
private byte[] resume;
My error :
Failed to convert property value of type org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile to required type byte[] for property resume; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile to required type byte for property resume[0]: PropertyEditor [org.springframework.beans.propertyeditors.CustomNumberEditor] returned inappropriate value of type org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile
Upvotes: 1
Views: 6629
Reputation: 1493
This is a common issue in handling the uploaded file in Spring MVC, which is unable to convert the uploaded file into byte arrays automatically. To make it work, you have to register a custom editor (ByteArrayMultipartFileEditor) in the SimpleFormController’s initBinder() method to guide Spring to convert the uploaded file into byte array.
in your controller use this:
@Override
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder)
throws ServletException {
// Convert multipart object to byte[]
binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor());
}
if you are using annotated controller, instead of overriding, use the annotation @InitBinder
you can find more explanation by following this link: https://mkyong.com/spring-mvc/spring-mvc-failed-to-convert-property-value-in-file-upload-form/
i got the answer there and i wanted to share it with u
Upvotes: 1
Reputation: 1254
Make sure you provide enctype="multipart/form-data" in your upload form from front-end application.
Below is a sample example(spring boot with hibernate/jpa) for persisting image data as byte[] (lob/blob) into mysql database:
Controller:
public ResponseEntity<?> uploadFile(@NotBlank @PathVariable String userId,
@RequestParam(value = "profileType", defaultValue = "LOGO", required = false) String profileType,
@RequestParam("avatarFile") MultipartFile avatarFile) {
return userService.storeFile(user, profileType, avatarFile);
}
Service:
@Override
public userImageData storeFile(user user, String profileType, MultipartFile file) {
log.debug(String.format("Executing < %s.%s#%s()", THIS_CLASS.getPackage().getName(),this.getClass(), new Object() {}.getClass().getEnclosingMethod().getName()));
if(file != null && !isEmpty(file.getOriginalFilename())){
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
try {
if (fileName.contains("..")) {
throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName);
}
userImageData userAvatar = new userImageData();
Optional<userImageData> userAvatarOp = imageDataRepository.findByuserImageDatauserEqualsAndImageTypeEquals(user, profileType);
if(userAvatarOp.isPresent()){
userAvatar = userAvatarOp.get();
}
userAvatar.setuserImageDatauser(user);
userAvatar.setImageType(profileType);
userAvatar.setFileName(fileName);
userAvatar.setFileType(file.getContentType());
userAvatar.setData(file.getBytes());
userAvatar.setFileSize(file.getSize());
userAvatar.setUploadId(UUID.randomUUID().toString());
return imageDataRepository.save(userAvatar);
} catch (IOException ex) {
throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex);
}
}
log.error("Invalid user image data. Please try again!");
return null;
}
Pojo:
@Entity
@Table(name = "user_avatar")
public class userImageData {
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
@Column(name = "user_avatar_Id")
private String userImageId;
@ManyToOne
@JoinColumn(name = "user_id")
@JsonIgnore
private user userImageDatauser;
private String imageType;
private String fileName;
private String fileType;
private Long fileSize;
@Lob
private byte[] data;
@Transient
private String fileAccessUri;
@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
private String uploadId;
}
Upvotes: 3