无法在Spring MVC中通过Ajax从JSP传递多部分文件至控制器

huangapple go评论87阅读模式
英文:

Unable to pass multipart file using Ajax from JSP to Controller in Spring MVC

问题

<div class="container-fluid">
    <div class="card">
        <div class="card-header bg-info"> BERICHT DATEI IMPORTIEREN </div>
        <div class="card-body">
            <form id="blkuploadform1" enctype="multipart/form-data">
                <div class="form-group">
                    <h6>Datei Importieren Method :</h6>
                    <p>Diese Seite wird verwendet, um die Datei mit 1 oder mehr als 1 Berichtsdatensätzen gleichzeitig in die Datenbank hochzuladen.</p>
                    <br>
                    <div class="custom-file">
                        <input type="file" class="custom-file-input" id="blkUploadReport1" name="blkUploadReport1">
                        <label class="custom-file-label" for="blkUploadReport1">Choose the File <span class="fas fa-asterisk"></span></label>
                    </div>
                </div>
            </form>
            <div class="col-sm-offset-2 col-sm-6">
                <button class="btn btn-success btn-raised btn-sm" id="saveEdit1" onClick="bulkupdValidator1()"> IMPORTIEREN <span class="fas fa-save"></span></button>
            </div>
        </div>
    </div>
    <br><br>
    <div class="card">
        <div class="card-header bg-info">
            BERICHT DATEI IMPORTIEREN
        </div>
        <div class="card-body">
            <form id="blkuploadform2" enctype="multipart/form-data">
                <div class="form-group">
                    <h6>Datei Importieren Method :</h6>
                    <p>Diese Seite wird verwendet, um die Datei mit 1 oder mehr als 1 Berichtsdatensätzen gleichzeitig in die Datenbank hochzuladen.</p>
                    <br>
                    <input type="file" id="blkUploadReport2" name="blkUploadReport2">  <span class="fas fa-asterisk"></span>
                </div>
            </form>
            <div class="col-sm-offset-2 col-sm-6">
                <button class="btn btn-success btn-raised btn-sm" id="saveEdit2" onClick="bulkupdValidator2()">
                    IMPORTIEREN <span class="fas fa-save"></span> 
                </button>					
            </div>
        </div>
    </div>
</div>

Controller:

@RequestMapping(value="/bulkuploadreportstg",method=RequestMethod.POST)
public List<DTSBlkReportStg> blkReportStg (@RequestParam("blkreportexcel") MultipartFile blreportexcel) {
    
    List<DTSBlkReportStg> stgresp= null;
    logger.info(blreportexcel);
    return stgresp;
}

Script:

function bulkupdValidator2(){
    if($('#blkuploadform2').valid()){
        $('#confirm-save').modal('show');
        console.log("I am success");
    }
    else{
        document.getElementById("error").innerText="Bitte füllen Sie die erforderlichen Felder mit rotem Text aus.";
        $('#error-message').modal('show');
    }
}

$(document).ready(function(){
    $('#blkuploadform2').validate({
        rules:{
            blkUploadReport2:{
                required:true,
                extension:'xlsx'
            }
        },
        messages:{
            blkUploadReport2:{
                required:"Bitte laden Sie die Datei im gewünschten Format (.xlsx) hoch.",
                extension:"Bitte laden Sie die Datei im gewünschten Format (.xlsx) hoch."
            }
        }
    })
})

//Function to Validate the data from uploaded file and load them into staging tables accordingly.

function blksavedata(typeOfData){
    $('#confirm-save').modal('hide');
    var form=$('#blkuploadform2')[0]
    console.log($('#blkuploadform2')[0]);
    var data=new FormData(form.files);
    console.log(data);
    
    if (fileType=='report')
    {
        $.ajax({
            type:"POST",
            url:"/DTSDBL/bulkuploadreportstg?blreportexcel="+data,
            processData: false,
            enctype: "multipart/form-data",
            contentType: false,
            cache: false,
            success:function(data){	                                     		 
                console.log("I am success returned form controller"); 		                                     		 
            },
            error:function(e){
                console.log("I am error returned form controller"); 			 
            }
        });
    }
}

Below is the error received in Controller log:

2020-07-28 16:57:54,804 [http-nio-8080-exec-415] DEBUG o.s.web.servlet.DispatcherServlet - Could not complete request
org.springframework.web.multipart.MultipartException: Current request is not a multipart request
at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:190)
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:109)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158)
// ... rest of the stack trace ...
英文:

I am trying to create file upload JSP and in this I am not using default SUBMIT type button. Instead I am using normal button and I have set onClick function. After onClick function triggered, Form is successfully Validating but the AJAX function is not able to send multipart file request to the controller. Below mentioned is the respective JSP, Controller and the script.

**

  • JSP:

&lt;div class=&quot;container-fluid&quot;&gt;
&lt;div class=&quot;card&quot;&gt;
&lt;div class=&quot;card-header bg-info&quot;&gt; BERICHT DATEI IMPORTIEREN &lt;/div&gt;
&lt;div class=&quot;card-body&quot;&gt;
&lt;form id=&quot;blkuploadform1&quot;  enctype=&quot;multipart/form-data&quot;&gt;
&lt;div class=&quot;form-group&quot;&gt;
&lt;h6&gt;Datei Importieren Method :&lt;/h6&gt;
&lt;p&gt;Diese Seite wird verwendet, um die Datei mit 1 oder mehr als 1 Berichtsdatens&#228;tzen gleichzeitig in die Datenbank hochzuladen.&lt;/p&gt;
&lt;br&gt;
&lt;div class=&quot;custom-file&quot;&gt;
&lt;input type=&quot;file&quot; class=&quot;custom-file-input&quot; id=&quot;blkUploadReport1&quot; name=&quot;blkUploadReport1&quot;&gt;
&lt;label class=&quot;custom-file-label&quot; for=&quot;blkUploadReport1&quot;&gt;Choose the File &lt;span class=&quot;fas fa-asterisk&quot;&gt;&lt;/span&gt;&lt;/label&gt;	                        
&lt;/div&gt;
&lt;/div&gt;
&lt;/form&gt;
&lt;div class=&quot;col-sm-offset-2 col-sm-6&quot;&gt;
&lt;button class=&quot;btn btn-success btn-raised btn-sm&quot; id=&quot;saveEdit1&quot; onClick=&quot;bulkupdValidator1()&quot;&gt; IMPORTIEREN &lt;span class=&quot;fas fa-save&quot;&gt;&lt;/span&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;&lt;br&gt;
&lt;div class=&quot;card&quot;&gt;
&lt;div class=&quot;card-header bg-info&quot;&gt;
BERICHT DATEI IMPORTIEREN
&lt;/div&gt;
&lt;div class=&quot;card-body&quot;&gt;
&lt;form id=&quot;blkuploadform2&quot; enctype=&quot;multipart/form-data&quot;&gt;
&lt;div class=&quot;form-group&quot;&gt;
&lt;h6&gt;Datei Importieren Method :&lt;/h6&gt;
&lt;p&gt;Diese Seite wird verwendet, um die Datei mit 1 oder mehr als 1 Berichtsdatens&#228;tzen gleichzeitig in die Datenbank hochzuladen.&lt;/p&gt;
&lt;br&gt;
&lt;input type=&quot;file&quot; id=&quot;blkUploadReport2&quot; name=&quot;blkUploadReport2&quot;&gt;  &lt;span class=&quot;fas fa-asterisk&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;/form&gt;
&lt;div class=&quot;col-sm-offset-2 col-sm-6&quot;&gt;
&lt;button class=&quot;btn btn-success btn-raised btn-sm&quot; id=&quot;saveEdit2&quot; onClick=&quot;bulkupdValidator2()&quot;&gt;
IMPORTIEREN &lt;span class=&quot;fas fa-save&quot;&gt;&lt;/span&gt; 
&lt;/button&gt;					
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

**

**

  • CONTROLLER:
	@RequestMapping(value=&quot;/bulkuploadreportstg&quot;,method=RequestMethod.POST)
public List&lt;DTSBlkReportStg&gt; blkReportStg (@RequestParam(&quot;blkreportexcel&quot;) MultipartFile blreportexcel) {
List&lt;DTSBlkReportStg&gt; stgresp= null;
logger.info(blreportexcel);
return stgresp;
}

**

**

  • SCRIPT:
function bulkupdValidator2(){
if($(&#39;#blkuploadform2&#39;).valid()){
$(&#39;#confirm-save&#39;).modal(&#39;show&#39;);
console.log(&quot;I am success&quot;);
}
else{
document.getElementById(&quot;error&quot;).innerText=&quot;Bitte f&#252;llen Sie die erforderlichen Felder mit rotem Text aus.&quot;;
$(&#39;#error-message&#39;).modal(&#39;show&#39;);
}
}
$(document).ready(function(){
$(&#39;#blkuploadform2&#39;).validate({
rules:{
blkUploadReport2:{
required:true,
extension:&#39;xlsx&#39;
}
},
messages:{
blkUploadReport2:{
required:&quot;Bitte laden Sie die Datei im gew&#252;nschten Format (.xlsx) hoch.&quot;,
extension:&quot;Bitte laden Sie die Datei im gew&#252;nschten Format (.xlsx) hoch.&quot;
}
}
})
})
//Function to Validate the data from uploaded file and load them into staging tables accordingly.
function blksavedata(typeOfData){
$(&#39;#confirm-save&#39;).modal(&#39;hide&#39;);
var form=$(&#39;#blkuploadform2&#39;)[0]
console.log($(&#39;#blkuploadform2&#39;)[0]);
var data=new FormData(form.files);
console.log(data);
if (fileType==&#39;report&#39;)
{
$.ajax({
type:&quot;POST&quot;,
url:&quot;/DTSDBL/bulkuploadreportstg?blreportexcel=&quot;+data,
processData: false,
enctype: &quot;multipart/form-data&quot;,
contentType: false,
cache: false,
success:function(data){	  			
console.log(&quot;I am success returned form controller&quot;); 	                                     		 
},
error:function(e){
console.log(&quot;I am error returned form controller&quot;); 			 
}
});
}
}

**

Below is the error received in Controller log.

2020-07-28 16:57:54,804 [http-nio-8080-exec-415] DEBUG o.s.web.servlet.DispatcherServlet - Could not complete request
org.springframework.web.multipart.MultipartException: Current request is not a multipart request
at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:190)
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:109)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:660)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:808)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)

Can some one advise how to fix this ?

答案1

得分: 1

关于多部分配置,您必须确保将后端配置为在其依赖项中具有 commons-fileupload

从 Spring 的配置方面来看,您需要在应用上下文中注册此 bean。

public CommonsMultipartResolver multipartResolver() {
    CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
    multipartResolver.setMaxUploadSize(100000);
    return multipartResolver;
}

从控制器的角度来看,多部分数据不是请求参数,而是请求体的一部分,因此尝试在控制器中从 MultipartFile 前面移除 @RequestParam。

另外,关于请求,您的 JavaScript 脚本应该发送一个带有头部 "Accept: multipart/form-data" 的请求(可以通过 jquery 进行传递,或者在表单上进行设置)。

附注:
您还将文件通过 URL 参数发送。应该在请求的正文中发送,就像这里所示:

type: 'POST',
// 表单数据
data: new FormData($('form')[0]),
英文:

Regarding the multipart config you must be sure to have your backend configured to that it has a dependency to commons-fileupload in your dependencies.

From spring's configuration side, you need to register this bean in your application context.

public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(100000);
return multipartResolver;
}

And from the controller point of view, the multipart is not a requestParam, it's part of the body, so try removing the @RequestParam before MultipartFile from your controller.

Also regarding the request, your js script should do a request containing the header "Accept: multipart/form-data" (either pass it from jquery, or set it on your form)

LE:
Also you are sending the file via a url parameter. Send it in the body of the request as here ```

type: &#39;POST&#39;,
// Form data
data: new FormData($(&#39;form&#39;)[0]),

</details>
# 答案2
**得分**: 0
我能够通过将控制器类中的注释从 @Controller 更新为 @RestController,并根据 Alex 的说明,将 ajax 请求的发送方式从请求参数更改为请求主体,来解决这个问题。
<details>
<summary>英文:</summary>
I am able to fix the issue by updating the annotation from @Controller to @RestController in my Controller class and updated ajax request to send the file as Request Body instead of Request Param as mentioned by Alex.
</details>

huangapple
  • 本文由 发表于 2020年7月28日 23:07:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/63137304.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定