Reputation: 113
I am beginner in spring and i am creating a project using spring mvc 4 hibernate and mysql. In this project user would be able to submit a form with their profile picture "means, i need to submit data along with image file". I can store file as a blob in database but it is not a good practice, hence i am trying to store only name of a file in database.
What i've done so far: multipartviewresolver in my xml configuration, (commons fileupload, Commons io) in pom.xml, i'am using servlet api 2.5, i can upload imagefile in a database
I shall discuss my problem after showing my code,
This is my model class.
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@NotEmpty
@Size(max = 18, min = 5)
private String username;
//Alphanumeric password
@NotEmpty
private String password;
@NotEmpty
@Pattern(regexp="[^0-9]*")
private String fname;
private String mname;
@NotEmpty(message="Please Enter Lastname")
@Pattern(regexp="[^0-9]*")
private String lname;
@Pattern(regexp="[0-9]+")
private String roll;
private String faculty;
private String semester;
@NotNull
@DateTimeFormat(pattern="yyyy-mm-dd")
@Past
private Date dob;
private String gender ="male";
@NotEmpty
@Email
private String email;
@NotEmpty
@Pattern(regexp="[0-9]{10}")
private String contact;
@NotEmpty
private String address;
@NotEmpty
private String city;
private String country;
private int type;
private String image;
@Column(name = "created")
private Date created;
@Column(name = "updated")
private Date updated;
/*
@DateTimeFormat(pattern="yyyy-mm-dd hh:mm:ss")
private Date last_login;
*/
@NotEmpty
private String description;
This is my Html form :
<form:form
method="post" action="${pageContext.request.contextPath}/user/register"
modelAttribute="user"
enctype="multipart/form-data"
style="width:100%" >
<ul>
<li class="left">
<ul>
<li>Username <i>*</i></li>
<li>
<form:input class="fip" path="username" />
<form:errors path="username" cssClass="error" />
<!-- <span class="error">please enter valid information</span> -->
</li>
<li>First name <i>*</i> </li>
<li>
<form:input class="fip" path="fname" />
<form:errors cssClass="error" path="fname" />
</li>
<li>Last name <i>*</i> </li>
<li>
<form:input class="fip" path="lname" />
<form:errors cssClass="error" path="lname" />
</li>
<li>Faculty <i>*</i></li>
<li>
<form:select class="fsl" path="faculty">
<form:option value="NONE" label="--- Select faculty ---"/>
<form:options items="${Faculty}" />
</form:select>
</li>
<li>Email <i>*</i> </li>
<li>
<form:input class="fip" path="email" />
<form:errors cssClass="error" path="email" />
</li>
<li>Address <i>*</i> </li>
<li>
<form:input class="fip" path="address" />
<form:errors cssClass="error" path="address" />
</li>
<li>Country <i>*</i></li>
<li>
<form:select class="fsl" path="country">
<form:option value="NONE" label="--- Select Country ---"/>
<form:options items="${Country}" />
</form:select>
</li>
<li>Gender <i>*</i></li>
<li>
<div class="extra-bx">
<span><form:radiobutton value="male" path="gender"/> Male</span>
<span><form:radiobutton value="female" path="gender"/> Female</span>
</div>
</li>
</ul>
</li>
<li class="right">
<ul>
<li>Password <i>*</i> <small>(alphanumeric) exmple: nikesh9999</small> </li>
<li>
<form:input type="password" class="fip" path="password" />
<form:errors cssClass="error" path="password" />
</li>
<li>Mid name </li>
<li>
<form:input class="fip" path="mname" />
<form:errors cssClass="error" path="mname" />
</li>
<li>Roll <i>*</i> </li>
<li>
<form:input class="fip" path="roll" />
<form:errors cssClass="error" path="roll" />
</li>
<li>Semester <i>*</i></li>
<li>
<form:select class="fsl" path="semester">
<form:option value="NONE" label="--- Select Semester ---"/>
<form:options items="${Semester}" />
</form:select>
</li>
<li>Date of birth <i>*</i> </li>
<li>
<form:input class="fip datepicker" path="dob" />
<form:errors cssClass="error" path="dob" />
</li>
<li>Contact no. <i>*</i> </li>
<li>
<form:input class="fip" path="contact" />
<form:errors cssClass="error" path="contact" />
</li>
<li>City <i>*</i> </li>
<li>
<form:input class="fip" path="city" />
<form:errors cssClass="error" path="city" />
</li>
<li>Upload image <small>upload size (1 mb)</small></li>
<li>
<form:input type="file" class="fip" path="image" />
<form:errors cssClass="error" path="image" />
</li>
</ul>
</li>
<li>Description <i>*</i> <small> Describe yourself in words </small></li>
<li>
<form:textarea class="ckeditor" path="description" ></form:textarea>
<form:errors cssClass="error" path="description" />
</li>
<li class="submit">
<input type="submit" value="Save" name="submit" />
</li>
</ul>
</form:form>
This is my controller class
@Controller
@RequestMapping(value="/user")
public class userController {
@Autowired
private UserService userService;
@RequestMapping(value="/register",method = RequestMethod.GET)
public String userRegister (Model model) {
model.addAttribute("user", new User());
return "user/register";
}
@RequestMapping(value="/register", method = RequestMethod.POST)
public String saveUsers (HttpSession session, @ModelAttribute("user") @Valid User user, BindingResult result) {
if (result.hasErrors()){
return "user/register";
}
else {
// saving user
userService.saveUser(user);
// creating sesion
List<User> userlist = userService.createSession(user.getUsername(), user.getPassword());
iteratorUserList(session, userlist);
// redirecting
return "redirect:/user/"+user.getUsername();
}
}
The Problem is
you can see that i have a private image variable in my model class which is defined as a string and i also have same column name in my database which is defined as varchar. In order to store image filename.
I have a input type file in my html form and its path equals image.
In my save user method i have used @modelattribute(user), to map html form and model class.
when i submit my form i get the following error:
Failed to convert property value of type
[org.springframework.web.multipart.commons.CommonsMultipartFile]
to required type [java.lang.String] for property image; nested exception is
java.lang.IllegalStateException: Cannot convert value of type
[org.springframework.web.multipart.commons.CommonsMultipartFile] to required
type [java.lang.String] for property image: no matching editors or
conversion strategy found
I know the reason for this error : I have declared image variable as string type in my model class. I should not declare my image field as byte array [], cause its not good to store image in database indeed i want to save my image in server.
And the question remains : how can i store filename in database instead of file? how can i retrieve multipart file data which was sent to @modelattribute(user), so that i could save my image in server location? what should be added to my controller save method? i need a guidence for that
help me please, i have been wandering around the internet more than a weeks and i am not able to solve the problem. i only found byte array[] examples and thats not what i want,
thank you
Upvotes: 0
Views: 3475
Reputation: 113
What i am doing right now !! Here is my model class
@Transient
private CommonsMultipartFile[] imagefile;
private String image;
// and their respective setter and getter
Here is my html form
<li>Upload image <small>upload size (1 mb)</small></li>
<li>
<form:input type="file" class="fip" path="imagefile" />
<form:errors cssClass="error" path="imagefile" />
</li>
And my controller class
@RequestMapping(value="/register", method = RequestMethod.POST)
public String saveUsers (HttpSession session, @ModelAttribute("user") @Valid User user, BindingResult result) throws FileNotFoundException, IOException {
// Getting uploaded file from the request object
CommonsMultipartFile[] cMultFiles = user.getImagefile();
if (result.hasErrors()){
return "user/register";
}
else {
// Iterate through the multipart array
for (CommonsMultipartFile multipartFile : cMultFiles) {
// Save the file to local disk and name in database
user.setImage(saveFileToLocalDisk(multipartFile));
// saving user
userService.saveUser(user);
// creating sesion
List<User> userlist = userService.createSession(user.getUsername(), user.getPassword());
iteratorUserList(session, userlist);
}
// redirecting
return "redirect:/user/"+user.getUsername();
}
}
I could not achieve what i wanted by mapping varchar type'image' of database to commonmultipartfile type image in my model class. so i left image type as it was to string in my model class, and created new field instead with type commonmultipartfile and annotated it with @transient so that it wont be persisted. I fetched the multipartfile in controller and stored its name in database by using user.setImage(), and saved it in local storage normally.
thanks to you all for your effort.
Upvotes: 2
Reputation: 2587
Answer posted by 'Rahul Yadav' should help in resolving the error.
It would be good idea to store your files under particular folder on server. You could user user id itself for naming of your files. Which means no need to store file names explicitly in database, as you could derive it from your id. If you have multiple files to be stored, you could define a convention that could be followed for file naming.
Assuming you want to add User photographs, you can save it under some location say /userPhotos/ as:
/userPhotos/1.jpg
/userPhotos/2.jpg
If you are going to have multiple files associated to a user, you can create separate folder for each user Viz.
/data/1/1.jpg
/data/2/2.jpg
/someOtherFile.eg
Upvotes: 0
Reputation: 1513
You need to change the type of image
property to org.springframework.web.multipart.commons.CommonsMultipartFile
instead of String which would be array.
e.g. private CommonsMultipartFile[] image;
Then in your controller get using user.getImage()
, that will return you array of type CommonsMultipartFile
, iterate over it and using APIs for CommonsMultipartFile
you can get the image details and you can store the image to your server.
Upvotes: 2