【问题标题】:Upload CSV file from React and Spring Boot从 React 和 Spring Boot 上传 CSV 文件
【发布时间】:2021-03-01 12:10:33
【问题描述】:

也许有人知道如何解决上传文件到后端的问题。 Send file from Postman looks like 但是从 React 上传后,我有这样的异常:

2020-11-09 18:17:38.829 DEBUG 10764 --- [nio-8081-exec-7] osweb.servlet.DispatcherServlet:POST“/api/employees/save-from-csv”,参数= {masked} 2020-11-09 18:17:38.829 调试 10764 --- [nio-8081-exec-7] swsmmaRequestMappingHandlerMapping:映射到 com.bank.controller.EmployeeController#uploadFile(MultipartFile, Model) 2020-11- 09 18:17:38.831 调试 10764 --- [nio-8081-exec-7] .wsmmaServletInvocableHandlerMethod:无法解析公共 org.springframework.http.ResponseEntity com 中的参数 [0] .bank.controller.EmployeeController.uploadFile(org.springframework.web.multipart.MultipartFile,org.springframework.ui.Model) throws java.io.IOException: required request part 'file' is not present 2020-11-09 18: 17:38.831 调试 10764 --- [nio-8081-exec-7] .mmaExceptionHandlerExceptionResolver:使用 @ExceptionHandler com.bank.exceptions.FileUploadExceptionAdvice#handleException(Exception, WebRequest) 2020-11-09 18:17:38.832 调试 10764--- [nio-8081-exec-7] oswsmmaHttpEntityMethodProcessor:与 [application/json, text/plain, /] 不匹配,支持:[] 2020-11-09 18:17:38.833 WARN 10764 --- [ nio-8081-exec-7] .mmaExceptionHandlerExceptionResolver:已解决 [org.springframework.web.multipart.support.MissingServletRequestPartException:所需的请求部分“文件”不存在] 2020-11-09 18:17:38.837 DEBUG 10764 -- - [nio-8081-exec-7] osweb.servlet.DispatcherServlet:已完成 400 BAD_REQUEST

此代码用于从 React 表单发送文件:

class UploadFiles extends Component{

state = {
    file : ''
};

componentDidMount = () => {
    const {file} = this.props;
    this.setState({ file })
};

uploadFile = ({target : {files}}) => {
    console.log(files[0]);
    let data = new FormData();
    data.append('file', files);


    axios.post("/api/employees/save-from-csv", data)
        .then(res => {console.log(res)})
};

render(){
    return(
        <div className="container">
            <div className="row">
                <div className="col-md-6">
                    <div className="form-group files color">
                        <label>Upload Your File </label>
                        <input type="file" onChange={this.uploadFile}/>
                    </div>
                </div>
            </div>
        </div>
    )
}}

服务

public void csvToEmployees(@RequestParam("file") MultipartFile file, Model model) {
    // validate file
    if (file.isEmpty()) {
        model.addAttribute("message", "Please select a CSV file to upload.");
        model.addAttribute("status", false);
    } else {

        try (Reader reader = new BufferedReader(new InputStreamReader(file.getInputStream()))) {

            CsvToBean csvToBean = new CsvToBeanBuilder(reader)
                    .withType(Employee.class)
                    .withIgnoreLeadingWhiteSpace(true)
                    .build();

            List users = csvToBean.parse();
            employeeRepository.saveAll(users);

            model.addAttribute("users", users);
            model.addAttribute("status", true);

        } catch (Exception ex) {
            model.addAttribute("message", "An error occurred while processing the CSV file.");
            model.addAttribute("status", false);
        }
    }

}

控制器

 @PostMapping("/employees/save-from-csv")
public ResponseEntity<ResponseMessage> uploadFile(@RequestParam("file") MultipartFile file, Model model) throws IOException {
    ResponseEntity<ResponseMessage> result = null;
    boolean finished = false;
    String message = "";

    if (CSVHelper.hasCSVFormat(file)) {
        try {
            service.csvToEmployees(file, model);
            message = "Uploaded the file successfully: " + file.getOriginalFilename();
            result = ResponseEntity.status(HttpStatus.OK).body(new ResponseMessage(message));
            finished = true;
        } catch (Exception e) {
            message = "Could not upload the file: " + file.getOriginalFilename() + "!";
            message += e;
            result = ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY).body(new ResponseMessage(message));
            finished = true;
        }
    }
    if (!CSVHelper.hasCSVFormat(file)){

        message = "File is empty!";
        result = ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ResponseMessage(message));
    }
    if (!finished) {
        message = "Please upload a csv file!";
        result = ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseMessage(message));
    }
    return result;
}

CSVHelper

public class CSVHelper {

    public static boolean hasCSVFormat(MultipartFile file) {

        String TYPE = "text/csv";
        return TYPE.equals(file.getContentType());
    }

    public static List<Employee> csvToEmployees(InputStream is) {
        try (BufferedReader fileReader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
             CSVParser csvParser = new CSVParser(fileReader,
                     CSVFormat.DEFAULT.withFirstRecordAsHeader().withIgnoreHeaderCase().withTrim());) {

            List<Employee> employees = new ArrayList<>();

            Iterable<CSVRecord> csvRecords = csvParser.getRecords();

            for (CSVRecord csvRecord : csvRecords) {
                Employee employee = new Employee(
                        Long.parseLong(csvRecord.get("Id")),
                        csvRecord.get("Name"),
                        Long.parseLong(csvRecord.get("DepartmentId")),
                        Double.parseDouble(csvRecord.get("Salary")),
                        csvRecord.get("City"),
                        csvRecord.get("Street"),
                        csvRecord.get("BankName"),
                        csvRecord.get("CardNumber")
                );

                employees.add(employee);
            }

            return employees;
        } catch (IOException e) {
            throw new RuntimeException("fail to parse CSV file: " + e.getMessage());
        }
    }

}

单元测试

@Test
    public void saveEmployeesFromCSV() throws Exception {
        String url = "/api/employees/save-from-csv";


        String csvBuilder = "name,departmentId,salary,city,street,bankName,cardNumber\n" +
                "Maxim,1,3855,Madrid,Street,Bank York,NY98675432100\n";
        InputStream is = new ByteArrayInputStream(csvBuilder.getBytes());

        MockMultipartFile mockFile = new MockMultipartFile("file", "employees.csv", "text/csv", is);

        MockHttpServletResponse responseMessage = mvc.perform(MockMvcRequestBuilders.multipart(url)
                .file(mockFile)
                .param("file", "employees2.csv"))
                .andReturn()
                .getResponse();
        assertEquals(responseMessage.getStatus(), 200);
    }

【问题讨论】:

  • 请发布您的端点代码,以便我们知道那里发生了什么
  • 嗨,阿米尔!我已经编辑了代码
  • 所以,据我测试,您的后端代码可以正常工作,我会尝试找出您的反应代码中的错误在哪里

标签: java reactjs spring-boot file-upload csv-import


【解决方案1】:

好吧,这花了我一些时间,虽然这是你犯的一个很小的错误。

在您的反应代码中,您设置文件数组,在您的FormData 中作为file 传递。

这里正确的做法是只设置数组的一个File作为FormData的内容:

uploadFile = ({target : {files}}) => {
    console.log(files[0]);
    let data = new FormData();
    data.append('file', files[0]); <- this here is where the error was


    axios.post("/api/employees/save-from-csv", data)
        .then(res => {console.log(res)})
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-23
    • 2020-02-23
    • 2019-05-05
    • 2020-11-28
    • 1970-01-01
    • 2017-12-30
    • 2019-04-15
    • 2017-10-20
    相关资源
    最近更新 更多