Để upload vào thư mục đang chạy web ta cần tạo cấu hình chuyển đổi upload file trên thư mục web đăng chạy trên server bằng cách tạo MvcConfig.java trong webapp như sau:
@Configuration
public class MvcConfig implements WebMvcConfigurer{
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String dirName = "images";
Path dir = Paths.get("images");
String uploadPath = dir.toFile().getAbsolutePath();
registry.addResourceHandler("/" + dirName + "/**").addResourceLocations("file:/" + uploadPath + "/");
}
}
Tạo thêm thư mục services trong src/main/java/webapp
Tạo thư mục images trong src/main/resources/static
Tạo StorageProperties.java trong thư mục services để khai báo đường dẫn images trên thư mục web resource như sau:
@ConfigurationProperties("storage")
public class StorageProperties {
private String location = "./src/main/resources/static/images";
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
Sau khi tạo class StorageProperties xong ta cấu hình chạy khi webapp được khởi tạo trong class WebStoreApplication như sau
@EnableConfigurationProperties(StorageProperties.class)
public class WebStoreApplication {
public static void main(String[] args) {
SpringApplication.run(WebStoreApplication.class, args);
}
}
Trong code trên ta chỉ thêm phần code @EnableConfigurationProperties(StorageProperties.class), để biết được đường dẫn lưu trữ file trong resources
Tạo Helper.java trong thư mục services để xử lý upload file với nội dung sau
public class Helper {
public static String saveFile(String uploadDir, MultipartFile file, int len) throws IOException {
Path path = Paths.get(uploadDir);
if(!Files.exists(path)) {
Files.createDirectories(path);
}
String name = file.getOriginalFilename();
String ext = name.substring(name.lastIndexOf('.'));
String fileName = randomString(len - ext.length()) + ext;
Path filePath = path.resolve(fileName);
file.transferTo(filePath);
return fileName;
}
public static String randomString(int len){
StringBuilder sb = new StringBuilder(len);
String pattern = "1234567890qwertyuiopasdfghjklzxcvbnm";
Random random = new Random();
for(int i = 0; i < len; i++){
sb.append(pattern.charAt(random.nextInt(pattern.length())));
}
return sb.toString();
}
}
Trong class trên có phương thức randomString để tạo chuỗi ngẫu nhiên với chiều dài truyền vào là len
Đối với phương thức saveFile xử lý với mục địch lưu trữ vào thư mục, trong quá trình lưu file cần tạo chuỗi ngẫu nhiên nhắm tránh trường hợp trùng tên tập tin, sẽ bị ghi đè
Trường hợp kích thước file vượt quá mặc định cho phép trong Spring MVC ta cần cấu hình kích thước tập tin tối đa có thể upload trong application.properties như sau
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
Tạo Image.java trong thư mục models để lưu trữ các thông tin như đường dẫn, kiểu tập tin, kích thước như trong code sau:
@Entity
public class Image {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ImageId")
private int id;
@Column(name = "ImageUrl")
private String url;
private long size;
private String type;
public Image() {
}
public Image(int id, String url, long size, String type) {
super();
this.id = id;
this.url = url;
this.size = size;
this.type = type;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
Tạo tiếp ImageRepository.java trong models với nội dung sau:
public interface ImageRepository extends CrudRepository<Image, Integer>{
}
Trong thư mục controllers tạo UploadController.java với nội dung sau:
@Controller
public class UploadController {
@Autowired
private ImageRepository repository;
@GetMapping("/upload")
public String index(Model model){
model.addAttribute("list", repository.findAll());
return "upload/index";
}
@GetMapping("/upload/add")
public String add(){
return "upload/add";
}
@PostMapping("/upload/add")
public String add(MultipartFile f){
try {
String fileName = Helper.saveFile("images", f, 32);
Image image = new Image(0, fileName, f.getSize(), f.getContentType());
repository.save(image);
return "redirect:/upload";
} catch (IOException e) {
e.printStackTrace();
}
return "upload/add";
}
}
Tạo thư mục upload trong templates
Trong thư mục upload tạo index.html với nội dung sau để hiển thị thông tin upload file như sau:
<a href="/upload/add">Add</a>
<table>
<tbody>
<tr th:each="o : ${list}">
<td th:text="${o.id}"></td>
<td>
<img th:src="@{/images/{url}(url=${o.url})}" width="80">
</td>
<td th:text="${o.type}"></td>
</tr>
</tbody>
</table>
Trong thư mục upload tiếp tục tạo add.html để upload file
<form enctype="multipart/form-data" method="post">
<div>
<label for="f">Image</label>
<div>
<input type="file" name="f" id="f" accept="image/*">
</div>
</div>
<div>
<button>Upload</button>
</div>
</form>