【问题标题】:Getting 405 error when uploading a pdf using Spring-boot, thymeleaf and dropzone.js使用 Spring-boot、thymeleaf 和 dropzone.js 上传 pdf 时出现 405 错误
【发布时间】:2019-11-25 14:52:57
【问题描述】:

我创建了一个简单的表单,以便将单个 PDF 文件上传到我的数据库中的 blob。我正在使用 thymeleaf + spring boot 和 dropzone.js。

我收到 405 错误 - 上传文件时方法不允许。

我已经尝试在我的控制器方法中添加一个@ResponseBody,但错误仍然存​​在。

这是我的 pdf-upload.html(百里香模板):

<html>
    <head>
       ...
            <script type="text/javascript">
            Dropzone.options.myAwesomeDropzone = {
        //      url: "[[@{/vouchers/uploadPdfFile}]]",
                paramName : "file", // The name that will be             used to transfer the file
                maxFilesize : 10, // MB
                addRemoveLinks : true,
                acceptedFiles : ".pdf",
                maxFiles : 1,
//              headers: {
//                  'X-CSRF-TOKEN': $('meta[name="token"]').attr('content')
//              }
            };
        </script>

....
</head>

....

<form th:action="@{/vouchers/uploadPdfFile}"
                            enctype="multipart/form-data" 
                            method="post" class="dropzone needsclick dz-clickable"
                            id="my-awesome-dropzone">

                            <div class="col-12" id="dropzone">
                                <div class="dz-message needsclick">
                                    Drop the PDF that will be attached to the Voucher...<br>
                                </div>
                            </div>
                            <input type="hidden" id="hd_voucher_id" th:value="${voucher.id}">
                        </form>


....
</html>

我的控制器如下所示:

   @RequestMapping(value = "/uploadPdfFile", method = RequestMethod.POST)
    public String uploadPdfPost(MultipartHttpServletRequest request) {

        try {
            Iterator<String> itr = request.getFileNames();

            while (itr.hasNext()) {
                String uploadedFile = itr.next();
                MultipartFile file = request.getFile(uploadedFile);
                String mimeType = file.getContentType();
                String filename = file.getOriginalFilename();
                byte[] bytes = file.getBytes();

                FileUpload newFile = new FileUpload(filename, bytes, mimeType);

                //fileUploadService.uploadFile(newFile);
            }
        } catch (Exception e) {
            return "vouchers/pdf-upload";
        }
        return "vouchers/pdf-upload";
    }

当提交表单时,我收到了我之前提到的 405 错误。

在日志控制台中,我收到以下错误:

2019-07-16 15:45:27 WARN  o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
2019-07-16 15:45:27 DEBUG o.s.web.servlet.DispatcherServlet - Exiting from "FORWARD" dispatch, status 405
2019-07-16 15:45:27 DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
2019-07-16 15:45:27 ERROR o.s.b.w.s.support.ErrorPageFilter - Cannot forward to error page for request [/vouchers/uploadPdfFile] as the response has already been committed. As a result, the response may have the wrong status code. If your application is running on WebSphere Application Server you may be able to resolve this problem by setting com.ibm.ws.webcontainer.invokeFlushAfterService to false

关于这里发生了什么的任何提示?

提前致谢 娟

【问题讨论】:

  • 看起来 POST 方法没有注册。您能否检查同一控制器中的其他方法是否有效?如果不是,则控制器本身可能存在问题。如果其他人确实工作正常,您可以使用 Postman 独立测试该方法。
  • 嗨,Nikhil,是的。还有一些其他 @RequestMappings 在同一个控制器中工作(包括 Get 和 Post )。实际上,如果我调试我的 uploadPdfPost() 方法,我将跳过方法行。
  • 您不应该将 CSRF 令牌作为隐藏字段提交到表单中吗?
  • 嗨 Catchwa,我有两个关于 CSRF 令牌的问题:1)Thymeleaf 自己在表单中添加了一个 csrf 令牌,2)如果您看到我的代码,则在初始化时尝试设置令牌Dropzone js 对象,但我无法解决问题。
  • Catchwa,这是生成的 HTML,您可以在其中看到 csrf 令牌:
    删除将附加到凭证的 PDF...

标签: spring-boot thymeleaf dropzone.js http-status-code-405


【解决方案1】:

我找到了解决方案。因为我花了两天时间处理这个问题,所以我将与社区分享它,也许这篇文章可以帮助某人......

首先,该问题与 CSRF 生成或发布无关。是一个完全不同的问题,伪装成 405 错误。这是关于此事的第一个结论:您可能会收到 405 错误,但它可能是由不同的错误生成的(内部服务器错误 - 在我的情况下为 500)。

我收到 500 错误的原因无关紧要,重要的是我如何断定 500 错误显示为 405 错误:我通过添加以下行来简单地从 Spring Boot 禁用 csrf 令牌机制我的应用配置(扩展 WebSecurityConfigurerAdapter 的类):

http
  .csrf().disable(); // this will disable the crsf token mechanism from the entire app. Be careful!!

当我禁用它时,出现了 500 错误,这是一个非常简单的错误(百里香解析表达式错误)。我解决了500,然后我再次启用csrf机制,它工作了!

希望将来能帮助别人。

问候 娟

【讨论】:

    【解决方案2】:

    正如 Juan 所指出的,405 错误很可能是由于 csrf 令牌。 Dropzone 在内部更改请求类型,这会导致 csrf 令牌发生更改,进而导致此异常。为了防止这种情况,您需要做的就是传递与表单中相同的 csrf 令牌。

    在您的表单中添加:

    元名称="_csrf" th:content="${_csrf.token}" 元名称="_csrf_header" th:content="${_csrf.headerName}

    并在js中添加:

    init: function() {
    dzClosure = this;
    document.getElementById("submit-form-btn").addEventListener("click", function(e) {
        e.preventDefault();
        e.stopPropagation();
        dzClosure.processQueue();
    });
    
    this.on("sending", function(data, xhr, formData) {
        var token = $("meta[name='_csrf']").attr("content");
        var header = $("meta[name='_csrf_header']").attr("content");    
        xhr.setRequestHeader(header, token);
     });
    

    }

    【讨论】:

      猜你喜欢
      • 2014-07-17
      • 1970-01-01
      • 2019-03-25
      • 2017-01-14
      • 1970-01-01
      • 2018-07-08
      • 2021-09-25
      • 2023-03-26
      • 2018-04-16
      相关资源
      最近更新 更多