java - 如何从接受来自客户端浏览器的post请求(表单数据->文件输入)的前端服务器发送文件到后端服务器(用于上传)?

标签 java spring spring-boot

我正在尝试构建一个前端和后端分离的系统,并通过基于用户 token 的授权的休息调用进行交互。前端和后端应用程序都基于Springboot构建。 Thymeleaf 用作渲染 html 页面的模板引擎。

我正在尝试为用户上传文件,我将尝试将其保存在后端服务器的文件系统中。我遇到的问题是,我在浏览器上上传的文件没有被序列化,无论是作为 byte[] (当我尝试将八位字节流作为内容类型发送时)还是作为 json (当我尝试将 json 作为内容发送时) -类型)。

此问题的相关html是:

<form id="doctorDetailsId" enctype="multipart/form-data">
<input name="firstName" placeholder="first name"/>
Profile pic: <input name="photo" type="file"/>
<input name="username" placeholder="user name"/>
<input name="password" placeholder="password"/>
<button type="submit">Submit</button>
</form>

单击提交按钮后,以下 js 代码将带参数的 ajax 调用发送到前端服务器。

  $("#doctorDetailsId").ajaxForm({
    url: '/doctor/add',
    type: 'post',
    processData: false,
    success: function (data) {
        console.log("Added Doctor! data = " + JSON.stringify(data))
    }
})

Ajax 请求发送正常,前端应用程序中的 Controller 接收到请求。

@RequestMapping(value = URLConstants.DOCTOR + "/add", method = RequestMethod.POST)
@ResponseBody
public Map<String, Object> addDoctor(MultipartHttpServletRequest request, HttpServletResponse response) throws Exception {
    String token = (String) request.getSession().getAttribute("token");
    String role = (String)       request.getSession().getAttribute("userRole");
    if (token != null && !token.isEmpty()) {
        if (role.equals(UserRole.ADMIN.getDescription())) {
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            String firstName = request.getParameter("firstName");
            MultipartFile multipartFile1 = request.getFile("photo");
//          Part file =   request.getPart("photo");
            DoctorCO doctorCO = new DoctorCO(firstName, multipartFile1);
            .
            .
            .
            String url = backendServerUrl + ":" + backendServerPort + BackApis.ADD_DOCTOR;
            //RequestResponseDTO requestResponseDTO = HttpUtils.postData(url,
                    token, RequestMethod.POST.toString(), doctorCO);
            RequestResponseDTO requestResponseDTO = HttpUtils.postDataWithoutJsonSerialising(url,
                    token, RequestMethod.POST.toString(), doctorCO);
            DoctorDto doctorDto = objectMapper.convertValue(requestResponseDTO.getData(), DoctorDto.class);
            .
            .
            return doctorDto;
        } else {
            return null;
        }
    }
    return null;
}

httpUtils.postData() 方法进行 Jackson 序列化,而另一个方法则获取传递的对象的字节数组。

public String toJson(Object o) {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
    if (o == null) {
        return null;
    }
    try {
        return mapper.writeValueAsString(o);
    } catch (Exception e) {
        logger.error(JacksonUtils.class.getSimpleName(), e);
        throw new RuntimeException(e);
    }
}

public static byte[] serialize(Object obj) throws IOException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ObjectOutputStream os = new ObjectOutputStream(out);
    os.writeObject(obj);
    return out.toByteArray();
}

当DoctorCO对象进行序列化时,没有任何方法能够序列化MultipartFile对象。

当我尝试使用序列化方法时出现此异常。

java.io.NotSerializableException: org.apache.catalina.core.ApplicationPart

我尝试使用 toJson 方法时的另一个异常与 stackOverflow 错误(无限递归)相关

*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
2016-12-21 20:23:11.493 ERROR 25797 --- [nio-8082-exec-1] com.src.main.utils.JacksonUtils          : JacksonUtils

com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]-.....>java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"]->java.io.FileOutputStream["fd"]->java.io.FileDescriptor["parent"])
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:706) ~[jackson-databind-2.8.1.jar:2.8.1]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.8.1.jar:2.8.1]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:693) ~[jackson-databind-2.8.1.jar:2.8.1]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690) ~[jackson-databind-2.8.1.jar:2.8.1]
.
.
.
.

我长期以来一直在寻找一种将文件从前端序列化到后端服务器的解决方案。请让我知道这里出了什么问题,或者如果有人有更好的解决方案以这种方式上传文件,请告诉我。如果需要,我很乐意提供更多详细信息。

最佳答案

我试图避免 Part 或 MultipartFile 对象的序列化。我将 MultipartFile 对象转换为 File 对象。序列化已实现,没有出现任何此类错误。

MultipartFile multipartFile1 = request.getFile("photo");
File imageFile = jacksonUtils.getFileOfMultipartFile(multipartFile1);

(以下 block 取自 here )

public File getFileOfMultipartFile(MultipartFile multipartFile) throws IOException {
    File convFile = new File(multipartFile.getOriginalFilename());
    convFile.createNewFile();
    FileOutputStream fos = new FileOutputStream(convFile);
    fos.write(multipartFile.getBytes());
    fos.close();
    return convFile;
}

关于java - 如何从接受来自客户端浏览器的post请求(表单数据->文件输入)的前端服务器发送文件到后端服务器(用于上传)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41265788/

相关文章:

java - 如何为两个解析器语法制作相同的词法分析器

java - 运行android项目时出现NoClassDefFoundError

ajax - 将数组提交给 Spring Controller

java - 使用 Spring 客户端浏览 HATEOAS

java - 如何初始化 spring-boot WebMvc? (ServletContext 始终为空)

mysql - HikariCP - MYSQL 连接关闭后不允许进行任何操作。可能考虑使用较短的 maxLifetime 值

带参数传递的 Java 并行 for 循环

java - 我如何区分两个端点,每个端点都有一个 PathVariable?

java - Spring Cache - 生成自定义缓存结果

java - 从其他一些 Arraylist 的元素填充 Arraylist。