Hiển thị các bài đăng có nhãn upload file. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn upload file. Hiển thị tất cả bài đăng

Thứ Năm, 2 tháng 1, 2014

Xử lý File Upload trong Spring MVC

Để upload file từ client lên server ta sử dụng thư viện apache common-io và giao diện MultipartResolver của Spring.
Example lấy từ đây http://diepviends.blogspot.com/2013/12/xu-ly-form-trong-spring-mvc.html
Đầu tiên add các thư viện cần thiết vào
mở file pom.xml thêm các dependency sau:

            commons-io
            commons-io
            2.1
        

            javax
            javaee-web-api
            6.0
            provided
        
Cấu hình bean cho dispatcher servlet
Vào /WEB-INF/spring/appServlet/servlet-context.xml định nghĩa bean xử lý MultipartFile

bây giờ cấu hình cho dispatcher servlet xử lý multipart vào web.xml thêm đoạn như sau:

  appServlet
  org.springframework.web.servlet.DispatcherServlet
  
   contextConfigLocation
   /WEB-INF/spring/appServlet/servlet-context.xml
  
  1
  
   5000000
  
 
Xong việc cấu hình.
xử lý file upload thì có 2 cách:
Cách 1: lưu trực tiếp file vào DB, dữ liệu file được lưu trữ là kiểu binary
Cách 2: lưu file vào một thư mục nào đó trên server và sau đó lưu trữ đường dẫn vào DB
Cách thứ 2 thường được sử dụng đối với ứng dụng có upload image từ client
Trong ví dụ này, ta sẽ demo cả 2 cách xử lý trên (cũng tương tự nhau)
Ví dụ của ta sẽ lưu dữ liệu image của product ( kiểu byte) vào trường image (cách 1)
và upload ảnh vào thư mục /resources/upload trên server sau đó lưu đường dẫn của file ảnh được upload lên server vào trường imagePath.(cách 2)
Cụ thể Product class sẽ như sau:
package vn.ds.store.domains;

import java.io.Serializable;

public class Product implements Serializable {
 /**
  * 
  */
 private static final long serialVersionUID = 1L;
 private String name;
 private String price;
 private byte[] image;
 private String imagePath;

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getPrice() {
  return price;
 }

 public void setPrice(String price) {
  this.price = price;
 }

 public byte[] getImage() {
  return image;
 }

 public void setImage(byte[] image) {
  this.image = image;
 }

 public String getImagePath() {
  return imagePath;
 }

 public void setImagePath(String imagePath) {
  this.imagePath = imagePath;
 }
 
}
File createProduct.jsp sẽ được sửa như sau:
  
  
create
Name
Price
Image
Chú ý thêm thuộc tính cho form tag để xử lý upload: enctype="multipart/form-data"
file listProduct.jsp sẽ là:

   
List of products
Name Price Image imagePath
${p.name} ${p.price}
Bây giờ ta sẽ viết phần quan trọng nhất - controller xử lý upload ProductController.java
package vn.ds.store.controllers;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import vn.ds.store.domains.Product;
import vn.ds.store.validators.ProductValidator;

@Controller
@RequestMapping("product")
public class ProductController {

 private ProductValidator validator = new ProductValidator();

 @RequestMapping(value = "create", method = RequestMethod.GET)
 public String doGet(Model model) {
  model.addAttribute("product", new Product());
  return "createProduct";
 }

 @RequestMapping(value = "save", method = RequestMethod.POST)
 public String doPost(@ModelAttribute Product product, Model model,
   BindingResult errors,
   @RequestParam(value = "file", required = false) MultipartFile file,
   HttpServletRequest request) {
  validator.validate(product, errors);
  if (errors.hasErrors()) {
   return "createProduct";
  }
  if (file != null) {
   byte[] fileContent = null;
   try {
    InputStream inputStream = file.getInputStream();    
    if (inputStream == null)
     System.out.println("File inputstream is null");
    // cach 1 - luu truc tiep
    fileContent = IOUtils.toByteArray(inputStream);    
    product.setImage(fileContent);    
    // cach 2 - upload vao thu muc
    String path = request.getSession().getServletContext().getRealPath("/") + "resources/upload/";
    FileUtils.forceMkdir(new File(path));
    File upload = new File (path + file.getOriginalFilename());
    file.transferTo(upload);
    String imagePath = request.getContextPath() + "/resources/upload/" + file.getOriginalFilename();
    product.setImagePath(imagePath);
    request.getSession().setAttribute("product", product);
    IOUtils.closeQuietly(inputStream);
   } catch (IOException ex) {
    System.out.println("Error saving uploaded file");
   }
  }
  ArrayList lst = new ArrayList();
  lst.add(product);
  model.addAttribute("products", lst);
  return "listProduct";
 }

 @RequestMapping(value = "/image", method = RequestMethod.GET)
 @ResponseBody
 public byte[] downloadImg(HttpServletRequest request) {
  Product product = (Product) request.getSession()
    .getAttribute("product");
  if (product != null)
   return product.getImage();
  else
   return null;
 }
}
Ở đây, ta lưu dữ liệu vào session để lấy ra sau (thông thường là lưu vào database, ở đây đang là demo). Cách 1 ta sẽ lưu dữ liệu vào biến image bằng hàm
IOUtils.toByteArray(inputStream); 
Sau đó ta định nghĩa một url mà để gọi đến trong src của thẻ img
url này chỉ gửi xuống client dữ liệu của image nên ta sử dụng @ResponseBody của spring hỗ trợ để làm việc đó (search google.com để biêt thêm chi tiết), dưới jsp ta chỉ cần gọi đến url này
Cách 2 ta sẽ coppy ảnh vào thư mục /resoures/upload để lấy đường dẫn vật lý trên server để tạo file ta dùng lệnh này:
String path = request.getSession().getServletContext().getRealPath("/") + "resources/upload/";
và để hiển thị file trên html, thẻ img chỉ hiển thị đường dẫn internet, ta sẽ lấy đường dẫn theo lệnh sau:
String imagePath = request.getContextPath() + "/resources/upload/" + file.getOriginalFilename();
và cuối cùng lệnh coppy data
file.transferTo(upload);
Kết quả:



source code:
https://www.mediafire.com/?4b23hkdzfhwil4g

Thanks & Regards!