Time for action – adding images to a product

Một phần của tài liệu Spring MVC beginners guide (Trang 150 - 155)

Let's add an image upload facility in our add products page:

Add a bean definition in our web application context configuration file

1. (WebApplicationContextConfig.java) for CommonsMultipartResolver as follows:

@Bean

public CommonsMultipartResolver multipartResolver() {

CommonsMultipartResolver resolver=new

CommonsMultipartResolver();

resolver.setDefaultEncoding("utf-8");

return resolver;

}

Open pom.xml, which you can find under the project root directory itself.

2.

You will be able to see some tabs under pom.xml; select the Dependencies tab

3. and click on the Add button of the Dependencies section.

A Select Dependency window will appear; in Group Id enter commons-

4.

fileupload, in Artifact Id enter commons-fileupload, in Version enter 1.2.2, select Scope as compile, then click on the OK button.

Similarly, add one more dependency: org.apache.commons as Group Id,

5.

commons-io as Artifact Id, 1.3.2 as Version, and Scope as compile, then click

on the OK button and save pom.xml.

Open our product's domain class (product.java) and add a reference to

6.

org.springframework.web.multipart.MultipartFile with corresponding setters and getters as follows (don't forget to add getters and setters for this field): private MultipartFile productImage;

Open addProduct.jsp, which you can find under

7. the/src/main/webapp/WEB-INF/views/ directory in your project, and add the following set of tags after the <form:input id="condition"> tag group:

<div class="form-group">

<label class="control-label col-lg-2" for="productImage"> <spring:message code="addProduct.form.productImage.label"/>

</label>

<div class="col-lg-10">

<form:input id="productImage" path="productImage"

Working with View Resolver

[ 138 ]

type="file" class="form:input-large" />

</div>

</div>

Add an entry in our message bundle source (messages.properties) for the

8. product's image label, as follows:

addProduct.form.productImage.label = Product Image file

Now set the enctype attribute to multipart/form-data in the form tag as

9. follows and save addProduct.jsp:

<form:form modelAttribute="newProduct" class="form-

horizontal" enctype="multipart/form-data">

Open our ProductController.java and modify the

10. processAddNewProductForm method's signature by adding an extra method parameter of the type HttpServletRequest

(javax.servlet.http.HttpServletRequest); so basically your

processAddNewProductForm method signature should look like the following code snippet:

public String processAddNewProductForm(

@ModelAttribute("newProduct") Product newProduct,

BindingResult result, HttpServletRequest request) {

Add the following code snippet inside the processAddNewProductForm

11. method just before productService.addProduct(newProduct):

MultipartFile productImage = newProduct.getProductImage();

String rootDirectory =

request.getSession().getServletContext().getRealPath("/");

if (productImage!=null && !productImage.isEmpty()) {

try {

productImage.transferTo(new

File(rootDirectory+"resources\\images"+

newProduct.getProductId() + ".png"));

} catch (Exception e) {

throw new RuntimeException("Product Image saving

failed", e);

}

}

Within the initialiseBinder method, add a productImage field to the

12. whitelisting set as follows:

Working with View Resolver

binder.setAllowedFields("productId",

"name",

"unitPrice",

"description",

"manufacturer",

"category",

"unitsInStock",

"condition",

"productImage");

Now run our application and enter the URL

13.

http://localhost:8080/webstore/market/products/add. You will be able to see our add products page with an extra input field so you can choose which file to upload. Just fill out all the information as usual and, importantly, pick an image file of your choice for the newly-added image file; click on the Add button. You will be able to see that the image has been added to the Products page and to the product details page.

The add products page with the image selection option

Working with View Resolver

[ 140 ]

What just happened?

Spring's CommonsMultipartResolver

(org.springframework.web.multipart.commons.CommonsMultipartResolver) class

is the thing that determines whether the given request contains multipart content and parses the given HTTP request into multipart files and parameters. That's the reason we created a bean for that class within our web application context in step 1. And, through the setMaxUploadSize property, we set a maximum of 10,240,000 bytes as the allowed file size to be uploaded:

@Bean

public CommonsMultipartResolver multipartResolver() {

CommonsMultipartResolver resolver=new CommonsMultipartResolver();

resolver.setDefaultEncoding("utf-8");

resolver.setMaxUploadSize(10240000);

return resolver;

}

From steps 2 to 5, we added some of the org.apache.commons libraries as our Maven dependencies. This is because Spring uses those libraries internally to support the file uploading feature.

Since the image that we were uploading belongs to a product, it is better to keep that image

as part of the product information; that's why in step 6 we added a reference to the

MultipartFile in our domain class (Product.java) and added corresponding setters and getters. This MultipartFile reference holds the actual product image file that we are uploading.

We want to incorporate the image uploading facility in our add products page; that's why, in the addProduct.jsp View file, we added a file input tag to choose the desired image:

<div class="form-group">

<label class="control-label col-lg-2" for="productImage"> <spring:message code="addProduct.form.productImage.label"/>

</label>

<div class="col-lg-10">

<form:input id="productImage" path="productImage" type="file"

class="form:input-large" />

</div>

</div>

In the preceding set of tags, the important one is the <form:input> tag, which has the type attribute as file so that it can make the Choose File button display the file chooser window. As usual, we want this form field to be bound with the domain object field; that's

Working with View Resolver

the reason we gave the path attribute as productImage. If you remember, this path name

is just the same MultipartFile reference name that we added in step 6.

As usual, we want to externalize the label message for this file input tag as well; that's why

we added <spring:message>, and in step 8 we added the corresponding message entry in the message source file (messages.properties).

Since our add product form is now capable of sending an image file as well as part of the request, we need to encode the request as a multipart request. This is why in step 9 we added the enctype attribute to the <form:form> tag and set its value as

multipart/form-data. The enctype attribute indicates how the form data should be encoded when submitting it to the server.

We wanted to save the image file in the server under the resources/images directory, as this directory structure will be available directly under the root directory of our web

application at runtime. So, in order to get the root directory of our web application, we need HttpServletRequest. See the following code snippet:

String rootDirectory =

request.getSession().getServletContext().getRealPath("/");

That's the reason we added an extra method parameter called request of the type

HttpServletRequest to our processAddNewProductForm method in step 10.

Remember, Spring will fill this request parameter with the actual HTTP request.

In step 11, we simply read the image file from the domain object and wrote it into a new file with the product ID as the name:

MultipartFile productImage = newProduct.getProductImage();

String rootDirectory =

request.getSession().getServletContext().getRealPath("/");

if (!productImage.isEmpty()) {

try {

productImage.transferTo(new

File(rootDirectory+"resources\\images"+newProduct.getProductId() +

".png"));

} catch (Exception e) {

throw new RuntimeException("Product Image saving failed", e);

}

}

Remember, we purposely saved the images with the product ID name because we have already designed our products (products.jsp) page and details (product.jsp) page accordingly to show the right image based on the product ID.

Working with View Resolver

[ 142 ]

And as a final step, we added the newly introduced productImage file to the whitelisting set in the binder configuration within the initialiseBinder method.

Now if you run your application and enter

http://localhost:8080/webstore/market/products/add, you will be able to see your add products page with an extra input field to choose the file to upload.

Một phần của tài liệu Spring MVC beginners guide (Trang 150 - 155)

Tải bản đầy đủ (PDF)

(342 trang)