无法使用 Ajax 将多部分文件从 JSP 传递到 Spring MVC 中的控制器

Posted

技术标签:

【中文标题】无法使用 Ajax 将多部分文件从 JSP 传递到 Spring MVC 中的控制器【英文标题】:Unable to pass multipart file using Ajax from JSP to Controller in Spring MVC 【发布时间】:2020-07-28 15:07:59 【问题描述】:

我正在尝试创建文件上传 JSP,在此我没有使用默认的 SUBMIT 类型按钮。相反,我使用的是普通按钮,并且设置了 onClick 功能。 onClick 函数触发后,Form 验证成功,但 AJAX 函数无法向控制器发送多部分文件请求。下面提到的是各自的JSP、Controller和脚本。

**

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] 调试 os.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)

有人可以建议如何解决这个问题吗?

【问题讨论】:

【参考方案1】:

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

从 spring 的配置方面,你需要在你的应用程序上下文中注册这个 bean。

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


从控制器的角度来看,multipart 不是 requestParam,它是主体的一部分,因此请尝试从控制器中删除 MultipartFile 之前的 @RequestParam。

另外关于请求,你的 js 脚本应该做一个包含标题“Accept: multipart/form-data”的请求(或者从 jquery 传递它,或者在你的表单上设置它)

乐: 您还通过 url 参数发送文件。将其发送到请求的正文中,如下所示 ```

type: 'POST',
// Form data
data: new FormData($('form')[0]),

【讨论】:

不幸的是,我已经尝试了您提到的所有方法,但仍然出现 500 错误。函数 blksavedata(typeOfData) var form=$('#blkuploadform2')[0] var formdata=new FormData(form); formdata.append("文件",form.files); $.ajax( type:"POST", url:"/bulkuploadreportstg?blreportexcel="+encodeURIComponent(formdata), processData: false, enctype: "multipart/form-data", Accept: "multipart/form-data",内容类型:假,缓存:假,成功:函数(数据),错误:函数(e)); 能否请您也给控制器sn-p?【参考方案2】:

我可以通过在我的 Controller 类中将注释从 @Controller 更新为 @RestController 并更新 ajax 请求以将文件作为请求正文而不是 Alex 提到的请求参数发送来解决此问题。

【讨论】:

以上是关于无法使用 Ajax 将多部分文件从 JSP 传递到 Spring MVC 中的控制器的主要内容,如果未能解决你的问题,请参考以下文章

我可以将变量从我的 javascript 传递到 jsp 文件吗?

如何将文本字段数据从 Struts 2 中的 ajax 操作传递到原始调用 .jsp?

Java ajax 将值从 jsp 传递到 servlet

Laravel 将数据从 ajax 传递到位于单独文件中的模态视图,导致模态视图无法呈现

ajax 将多部分表单数据作为 json 对象上传

如何将值从 ajax 传递到 portlet 页面