无法使用 Ajax 将多部分文件从 JSP 传递到 Spring MVC 中的控制器
Unable to pass multipart file using Ajax from JSP to Controller in Spring MVC
我正在尝试创建文件上传 JSP,在此我没有使用默认的提交类型按钮。相反,我使用的是普通按钮,并且设置了 onClick 函数。触发 onClick 函数后,表单已成功验证,但 AJAX 函数无法向控制器发送多部分文件请求。下面提到的是各自的JSP、控制器和脚本。
**
- JSP:
<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>
**
**
- 控制器:
@RequestMapping(value="/bulkuploadreportstg",method=RequestMethod.POST)
public List<DTSBlkReportStg> blkReportStg (@RequestParam("blkreportexcel") MultipartFile blreportexcel) {
List<DTSBlkReportStg> stgresp= null;
logger.info(blreportexcel);
return stgresp;
}
**
**
- 脚本:
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");
}
});
}
}
**
以下是控制器日志中收到的错误。
2020-07-28 16:57:54,804 [http-nio-8080-exec-415] DEBUG o.s.web.servlet.DispatcherServlet - 无法完成请求
org.springframework.web.multipart.MultipartException: 当前请求不是多部分请求
在 org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:190)
在 org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:109)
在 org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
在 org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158)
在 org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
在 org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
在 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
在 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
在 org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
在 org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
在 org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
在 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
在 org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
在 javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
在 org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
在 javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
在 org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
在 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
在 org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
在 org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
在 org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
在 org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:660)
在 org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
在 org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
在 org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
在 org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:808)
在 org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
在 org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
在 org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
在 java.lang.Thread.run(Thread.java:748)
有人可以建议如何解决这个问题吗?
关于多部分配置,您必须确保将后端配置为它在依赖项中依赖于 commons-fileupload
。
从 spring 的配置端,您需要在您的应用程序上下文中注册此 bean。
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(100000);
return multipartResolver;
}
从控制器的角度来看,multipart 不是 requestParam,它是 body 的一部分,因此请尝试从控制器中删除 MultipartFile 之前的 @RequestParam。
关于请求,您的 js 脚本应该执行包含 header“接受:multipart/form-data”的请求(从 jquery 传递它,或者在您的表单上设置它)
乐:
您还通过 url 参数发送文件。在请求的 body 中发送它,如下所示```
type: 'POST',
// Form data
data: new FormData($('form')[0]),
我可以通过在我的控制器 class 中将注释从 @Controller 更新为 @RestController 并更新 ajax 请求以将文件作为请求主体而不是请求参数发送来解决问题亚历克斯提到
我正在尝试创建文件上传 JSP,在此我没有使用默认的提交类型按钮。相反,我使用的是普通按钮,并且设置了 onClick 函数。触发 onClick 函数后,表单已成功验证,但 AJAX 函数无法向控制器发送多部分文件请求。下面提到的是各自的JSP、控制器和脚本。
**
- JSP:
<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>
**
**
- 控制器:
@RequestMapping(value="/bulkuploadreportstg",method=RequestMethod.POST)
public List<DTSBlkReportStg> blkReportStg (@RequestParam("blkreportexcel") MultipartFile blreportexcel) {
List<DTSBlkReportStg> stgresp= null;
logger.info(blreportexcel);
return stgresp;
}
**
**
- 脚本:
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");
}
});
}
}
**
以下是控制器日志中收到的错误。
2020-07-28 16:57:54,804 [http-nio-8080-exec-415] DEBUG o.s.web.servlet.DispatcherServlet - 无法完成请求 org.springframework.web.multipart.MultipartException: 当前请求不是多部分请求 在 org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:190) 在 org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:109) 在 org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) 在 org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158) 在 org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128) 在 org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) 在 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) 在 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) 在 org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) 在 org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) 在 org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) 在 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) 在 org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:660) 在 org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:741) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) 在 org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) 在 org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493) 在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137) 在 org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) 在 org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:660) 在 org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) 在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) 在 org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798) 在 org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) 在 org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:808) 在 org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498) 在 org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) 在 org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 在 java.lang.Thread.run(Thread.java:748)
有人可以建议如何解决这个问题吗?
关于多部分配置,您必须确保将后端配置为它在依赖项中依赖于 commons-fileupload
。
从 spring 的配置端,您需要在您的应用程序上下文中注册此 bean。
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(100000);
return multipartResolver;
}
从控制器的角度来看,multipart 不是 requestParam,它是 body 的一部分,因此请尝试从控制器中删除 MultipartFile 之前的 @RequestParam。
关于请求,您的 js 脚本应该执行包含 header“接受:multipart/form-data”的请求(从 jquery 传递它,或者在您的表单上设置它)
乐: 您还通过 url 参数发送文件。在请求的 body 中发送它,如下所示```
type: 'POST',
// Form data
data: new FormData($('form')[0]),
我可以通过在我的控制器 class 中将注释从 @Controller 更新为 @RestController 并更新 ajax 请求以将文件作为请求主体而不是请求参数发送来解决问题亚历克斯提到