Java 获得;“404未找到”;成功的FormData POST请求

Java 获得;“404未找到”;成功的FormData POST请求,java,spring,rest,spring-boot,spring-restcontroller,Java,Spring,Rest,Spring Boot,Spring Restcontroller,这可能很简单,但我现在真的无法理解。 FormData and File reach controller(数据和文件到达控制器)如预期一样,服务过程毫无例外地继续,但在浏览器中我得到一个状态代码:404 Not Found原因是什么?有什么想法吗 Ajax调用 $.ajax({ type: 'POST', contentType: false, processData: false, url: '/upload-form-and-attachment/',

这可能很简单,但我现在真的无法理解。
FormData and File reach controller(数据和文件到达控制器)如预期一样,服务过程毫无例外地继续,但在浏览器中我得到一个
状态代码:404 Not Found
原因是什么?有什么想法吗

Ajax调用

$.ajax({
    type: 'POST',
    contentType: false,
    processData: false,
    url: '/upload-form-and-attachment/',
    data: formData,
    dataType: 'text',
    success: function(response, textStatus) {
        displayPNotifyMessage(textStatus, '<spring:message code="something.success"/>'.format([response.operationData]), 'success');
    },
    error: function($data, textStatus, errorThrown) {
        displayPNotifyMessage(textStatus, errorThrown, 'error');
    },
    complete: function(){
        closeDialog();
    }
});
    var formData = new FormData();        
    formData.append('entityIds', $('#theDialog').data('brp').selectedEntityIds);
    formData.append('description', $("#description").val());
    formData.append('modeIds', $('select#otherEntityIds').val());
/*Here I append more fields to the form, and finally I append the input type file*/
    formData.append('attachment', $('input#attachment')[0].files[0]);
  @RequestMapping(value = "/upload-form-and-attachment/", method = RequestMethod.POST)
    public JSONResult uploadFormAndAttachment(
            @RequestParam("entityIds") List<Long> entityIds,
            @RequestParam("description") String description,
            @RequestParam("modeIds") List<Long> modeIds,
            MultipartHttpServletRequest request,
            HttpSession session) {          
        JSONResult jsonResult = new JSONResult();
        try {
            MultipartFile attachment = request.getFile("attachment");
            // Calling some service methods and passing them the form data
        } catch(Exception e) {
            LOGGER.error(e.getMessage());
        }       
        return jsonResult;
    }
POST /***/upload-form-and-attachment/ HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 27274
Accept: text/plain, */*; q=0.01
Origin: http://localhost:8080
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryJqb7gbJhzfXRBRX7
Referer: http://localhost:8080/****
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=*******
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Content-Language: en
Content-Type: text/html;charset=UTF-8
Date: Sat, 20 Apr 2019 05:24:22 GMT
Expires: Sat, 6 May 1995 12:00:00 GMT
Pragma: no-cache
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
控制器

$.ajax({
    type: 'POST',
    contentType: false,
    processData: false,
    url: '/upload-form-and-attachment/',
    data: formData,
    dataType: 'text',
    success: function(response, textStatus) {
        displayPNotifyMessage(textStatus, '<spring:message code="something.success"/>'.format([response.operationData]), 'success');
    },
    error: function($data, textStatus, errorThrown) {
        displayPNotifyMessage(textStatus, errorThrown, 'error');
    },
    complete: function(){
        closeDialog();
    }
});
    var formData = new FormData();        
    formData.append('entityIds', $('#theDialog').data('brp').selectedEntityIds);
    formData.append('description', $("#description").val());
    formData.append('modeIds', $('select#otherEntityIds').val());
/*Here I append more fields to the form, and finally I append the input type file*/
    formData.append('attachment', $('input#attachment')[0].files[0]);
  @RequestMapping(value = "/upload-form-and-attachment/", method = RequestMethod.POST)
    public JSONResult uploadFormAndAttachment(
            @RequestParam("entityIds") List<Long> entityIds,
            @RequestParam("description") String description,
            @RequestParam("modeIds") List<Long> modeIds,
            MultipartHttpServletRequest request,
            HttpSession session) {          
        JSONResult jsonResult = new JSONResult();
        try {
            MultipartFile attachment = request.getFile("attachment");
            // Calling some service methods and passing them the form data
        } catch(Exception e) {
            LOGGER.error(e.getMessage());
        }       
        return jsonResult;
    }
POST /***/upload-form-and-attachment/ HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 27274
Accept: text/plain, */*; q=0.01
Origin: http://localhost:8080
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryJqb7gbJhzfXRBRX7
Referer: http://localhost:8080/****
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=*******
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Content-Language: en
Content-Type: text/html;charset=UTF-8
Date: Sat, 20 Apr 2019 05:24:22 GMT
Expires: Sat, 6 May 1995 12:00:00 GMT
Pragma: no-cache
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Chrome控制台中的响应标题

$.ajax({
    type: 'POST',
    contentType: false,
    processData: false,
    url: '/upload-form-and-attachment/',
    data: formData,
    dataType: 'text',
    success: function(response, textStatus) {
        displayPNotifyMessage(textStatus, '<spring:message code="something.success"/>'.format([response.operationData]), 'success');
    },
    error: function($data, textStatus, errorThrown) {
        displayPNotifyMessage(textStatus, errorThrown, 'error');
    },
    complete: function(){
        closeDialog();
    }
});
    var formData = new FormData();        
    formData.append('entityIds', $('#theDialog').data('brp').selectedEntityIds);
    formData.append('description', $("#description").val());
    formData.append('modeIds', $('select#otherEntityIds').val());
/*Here I append more fields to the form, and finally I append the input type file*/
    formData.append('attachment', $('input#attachment')[0].files[0]);
  @RequestMapping(value = "/upload-form-and-attachment/", method = RequestMethod.POST)
    public JSONResult uploadFormAndAttachment(
            @RequestParam("entityIds") List<Long> entityIds,
            @RequestParam("description") String description,
            @RequestParam("modeIds") List<Long> modeIds,
            MultipartHttpServletRequest request,
            HttpSession session) {          
        JSONResult jsonResult = new JSONResult();
        try {
            MultipartFile attachment = request.getFile("attachment");
            // Calling some service methods and passing them the form data
        } catch(Exception e) {
            LOGGER.error(e.getMessage());
        }       
        return jsonResult;
    }
POST /***/upload-form-and-attachment/ HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 27274
Accept: text/plain, */*; q=0.01
Origin: http://localhost:8080
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryJqb7gbJhzfXRBRX7
Referer: http://localhost:8080/****
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=*******
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Content-Language: en
Content-Type: text/html;charset=UTF-8
Date: Sat, 20 Apr 2019 05:24:22 GMT
Expires: Sat, 6 May 1995 12:00:00 GMT
Pragma: no-cache
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
将contentType更改为“多部分/表单数据”
如答案所示,将contentType更改为“multipart/form data”的明显解决方案失败,并在API中产生以下错误

org.springframework.web.multipart.MultipartException: 
Failed to parse multipart servlet request; 
nested exception is org.apache.commons.fileupload.FileUploadException: 
the request was rejected because no multipart boundary was found
将contentType更改为“application/x-www-form-urlencoded”
使用此内容类型会在API中导致以下错误,因为整个请求显然是“字符串化”的,API无法识别传递的参数

org.springframework.web.bind.MissingServletRequestParameterException:  
Required List parameter 'entityIds' is not present
或者尝试使用@modeldattribute

var formData=new formData($('form#form_name')[0])接收数据;
var formData= new FormData($('form#form_name')[0]);

$.ajax({
    type: 'POST',
    url: '/upload-form-and-attachment/',
    data: formData,
    success: function(response, textStatus) {
        displayPNotifyMessage(textStatus, '<spring:message code="something.success"/>'.format([response.operationData]), 'success');
    },
    error: function($data, textStatus, errorThrown) {
        displayPNotifyMessage(textStatus, errorThrown, 'error');
    },
    complete: function(){
        closeDialog();
    }
});
$.ajax({ 键入:“POST”, url:“/上传表单和附件/”, 数据:formData, 成功:功能(响应、文本状态){ displayPNotifyMessage(textStatus,,.format([response.operationData]),“success”); }, 错误:函数($data、textStatus、ERRORSHORN){ displayPNotifyMessage(textStatus,errorshown,'error'); }, 完成:函数(){ closeDialog(); } });

创建一个与formData中的字段相同的类,然后您可以使用@ModelAttribute获取这些字段。嗨,您能向我解释一下这到底有什么帮助吗?您是否建议用对象替换FormData?我不认为这是问题所在,您也可以编辑此答案而不是发布新答案。在这种情况下,ContentType和ProcessType应该是什么?你试过这种方法吗?
var formData= new FormData($('form#form_name')[0]);

$.ajax({
    type: 'POST',
    url: '/upload-form-and-attachment/',
    data: formData,
    success: function(response, textStatus) {
        displayPNotifyMessage(textStatus, '<spring:message code="something.success"/>'.format([response.operationData]), 'success');
    },
    error: function($data, textStatus, errorThrown) {
        displayPNotifyMessage(textStatus, errorThrown, 'error');
    },
    complete: function(){
        closeDialog();
    }
});