Lỗi không nhận được tệp khi tải lên qua form

Khi triển khai chức năng tải tệp lên bằng Java, gặp phải vấn đề backend không thể nhận được dữ liệu tệp. Cụ thể như sau:

Phương thức xử lý tệp trong Controller được viết như sau:

/**
 * Tải tệp lên
 * @since 2018-05-22
 * @return
 */
@ApiOperation(value="Tải tệp", notes = "Giao diện tải tệp")
@RequestMapping(value = "/tai-len", consumes = "multipart/form-data;charset=utf-8", produces = "text/plain;charset=utf-8", method = RequestMethod.POST)
public @ResponseBody ResponseEntity<String> taiLen(HttpServletRequest request) {
    byte[] duLieuTep = null;
    String hashTep = "";

    HashMap<String, String> ketQua = new HashMap<>();
    if (request instanceof MultipartHttpServletRequest) {
        MultipartHttpServletRequest yeuCau = (MultipartHttpServletRequest) request;
        List<MultipartFile> danhSachTep = yeuCau.getFiles("tep");
        if(danhSachTep.size() > 0) {
            for (MultipartFile tep : danhSachTep) {
                /***/
            }
            ketQua.put("maTrangThai", "0000");
            ketQua.put("thongBao", null);
            ketQua.put("hashTep", hashTep);
        }else{
            ketQua.put("maTrangThai", "THAT_BAI");
            ketQua.put("thongBao", "Không có tệp");
            ketQua.put("hashTep", hashTep);
        }
    }
    return ResponseEntity.ok(JSONUtils.toJSONString(ketQua));
}

Thử nghiệm bằng Postman thành công nhưng khi gọi từ chương trình khác thì danh sách tệp luôn trống:

List<MultipartFile> danhSachTep = yeuCau.getFiles("tep");

Kiểm tra nhiều cách như thay đổi Content-Type, thay đổi kiểu tham số thành MultipartFile... nhưng vẫn không nhận được tệp. Cuối cùng phát hiện vấn đề nằm ở tham số truyền vào phương thức getFiles() không khớp với tên trường tệp phía client.

Ví dụ frontend sử dụng HTML/JS:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Tải tệp</title>
    <script type="text/javascript" src="tai_len.js"></script>
    <script type="text/javascript" src="jquery-1.8.2.min.js"></script>
</head>
<body>
<form enctype = "multipart/form-data;charset=utf-8" name="form_tai_len" action="" method="POST">
    <input type ="file" name="tep" id="tep"/><br/>
    Ghi chú:<input type="text" name="du_lieu" id="du_lieu"/><br/>
    <input type="button" value="Xác nhận" onclick="taiLen()"/><br/>
</form>
</body>
</html>

Và đoạn JS:

function taiLen() {
    duLieu = document.getElementById("tep").files[0];
    duLieuForm = new FormData();
    duLieuForm.append("tep", duLieu);
    $.ajax({
        url:"http://xxx/file/tai-len",
        type:"POST",
        data:duLieuForm,
        dataType:"text",
        processData: false,
        contentType: false,
        success: function(ketQua){
            alert(ketQua);
        }
    });
}

Tên trường "tep" trong frontend phải khớp với tham số truyền vào getFiles() ở backend, nếu không sẽ không nhận được tệp.

Lưu ý thêm về cấu hình giới hạn kích thước tệp trong Spring Boot. Mặc định là 1MB, vượt quá sẽ báo lỗi:

org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: Trường tep vượt quá giới hạn 1048576 bytes

Để sửa, thêm cấu hình sau vào class Application:

/**
 * Cấu hình tải tệp
 * @return
 */
@Bean
public MultipartConfigElement cauHinhTep() {
    MultipartConfigFactory factory = new MultipartConfigFactory();
    // Giới hạn kích thước tệp
    factory.setMaxFileSize("10240KB"); 
    // Giới hạn tổng kích thước yêu cầu
    factory.setMaxRequestSize("102400KB");
    return factory.createMultipartConfig();
}

Các giá trị in đậm là kích thước mong muốn.

Thẻ: Java Spring Boot Tải tệp MultipartFormData MultipartFile

Đăng vào ngày 21 tháng 6 lúc 01:32