【问题标题】:Using PUT method in HTML form在 HTML 表单中使用 PUT 方法
【发布时间】:2011-12-24 15:30:49
【问题描述】:

我可以在 HTML 表单中使用 PUT 方法将数据从表单发送到服务器吗?

【问题讨论】:

    标签: html forms http


    【解决方案1】:

    我写了一个名为“html-form-enhancer”的npm package。通过将其放入您的 HTML 源代码中,它会接管使用除 GETPOST 之外的方法提交的表单,并添加 application/json 序列化。

    <script type=module" src="html-form-enhancer.js"></script>
    
    <form method="PUT">
    ...
    </form>
    

    【讨论】:

      【解决方案2】:

      对于使用 laravel 的人

      <form method="post" ...>
      @csrf
      @method('put')
      ...
      </form>
      

      【讨论】:

      • 代码不仅仅是解决方案。也请添加描述。谢谢。
      • @Rayees AC,这是为那些在 Laravel 框架中工作的人提供的解决方案,仅供参考。在帖子顶部写了粗体。没有得到你的意思,否则
      • 虽然 SO 明智地鼓励人们不要只发布代码答案,但有时......像这种情况......这就是你所需要的。
      【解决方案3】:

      如果您使用的是 nodejs,您可以安装包 method-override,它允许您使用中间件执行此操作。 文档链接:http://expressjs.com/en/resources/middleware/method-override.html

      安装后,我所要做的就是:

      var methodOverride = require('method-override')
      app.use(methodOverride('_method'))
      

      【讨论】:

        【解决方案4】:

        _method隐藏字段解决方法

        一些网络框架使用了以下简单的技术:

        • 向任何不是 GET 或 POST 的表单添加隐藏的 _method 参数:

          <input type="hidden" name="_method" value="PUT">
          

          这可以通过 HTML 创建辅助方法在框架中自动完成。

        • 将实际表单方法修复为 POST (&lt;form method="post")

        • 在服务器上处理 _method 并完全按照发送该方法而不是实际 POST 的方式进行操作

        您可以通过以下方式实现:

        • 导轨:form_tag
        • Laravel:@method("PATCH")

        为什么在纯 HTML 中不可能实现的理由/历史:https://softwareengineering.stackexchange.com/questions/114156/why-there-are-no-put-and-delete-methods-in-html-forms

        【讨论】:

        • Laravel (php) 使用@method("PATCH")具有相同的功能
        • 这似乎是一个合理的解决方法,但仍然很不幸,因为它使调试变得困难。例如,如果您需要通过服务器日志或进行网络分析来验证某些内容,您将看不到正确的输出,因为 HTTP 标头中使用的 HTTP 方法仍然是POST,而不是您实际需要的。
        【解决方案5】:

        设置方法 PUT 和 DELETE 我执行如下:

        <form
          method="PUT"
          action="domain/route/param?query=value"
        >
          <input type="hidden" name="delete_id" value="1" />
          <input type="hidden" name="put_id" value="1" />
          <input type="text" name="put_name" value="content_or_not" />
          <div>
            <button name="update_data">Save changes</button>
            <button name="remove_data">Remove</button>
          </div>
        </form>
        <hr>
        <form
          method="DELETE"
          action="domain/route/param?query=value"
        >
          <input type="hidden" name="delete_id" value="1" />
          <input type="text" name="delete_name" value="content_or_not" />
          <button name="delete_data">Remove item</button>
        </form>
        

        然后 JS 执行所需的方法:

        <script>
           var putMethod = ( event ) => {
             // Prevent redirection of Form Click
             event.preventDefault();
             var target = event.target;
             while ( target.tagName != "FORM" ) {
               target = target.parentElement;
             } // While the target is not te FORM tag, it looks for the parent element
             // The action attribute provides the request URL
             var url = target.getAttribute( "action" );
        
             // Collect Form Data by prefix "put_" on name attribute
             var bodyForm = target.querySelectorAll( "[name^=put_]");
             var body = {};
             bodyForm.forEach( element => {
               // I used split to separate prefix from worth name attribute
               var nameArray = element.getAttribute( "name" ).split( "_" );
               var name = nameArray[ nameArray.length - 1 ];
               if ( element.tagName != "TEXTAREA" ) {
                 var value = element.getAttribute( "value" );
               } else {
               // if element is textarea, value attribute may return null or undefined
                 var value = element.innerHTML;
               }
               // all elements with name="put_*" has value registered in body object
               body[ name ] = value;
             } );
             var xhr = new XMLHttpRequest();
             xhr.open( "PUT", url );
             xhr.setRequestHeader( "Content-Type", "application/json" );
             xhr.onload = () => {
               if ( xhr.status === 200 ) {
               // reload() uses cache, reload( true ) force no-cache. I reload the page to make "redirects normal effect" of HTML form when submit. You can manipulate DOM instead.
                 location.reload( true );
               } else {
                 console.log( xhr.status, xhr.responseText );
               }
             }
             xhr.send( body );
           }
        
           var deleteMethod = ( event ) => {
             event.preventDefault();
             var confirm = window.confirm( "Certeza em deletar este conteúdo?" );
             if ( confirm ) {
               var target = event.target;
               while ( target.tagName != "FORM" ) {
                 target = target.parentElement;
               }
               var url = target.getAttribute( "action" );
               var xhr = new XMLHttpRequest();
               xhr.open( "DELETE", url );
               xhr.setRequestHeader( "Content-Type", "application/json" );
               xhr.onload = () => {
                 if ( xhr.status === 200 ) {
                   location.reload( true );
                   console.log( xhr.responseText );
                 } else {
                   console.log( xhr.status, xhr.responseText );
                 }
               }
               xhr.send();
             }
           }
        </script>
        

        定义了这些函数后,我将一个事件监听器添加到发出表单方法请求的按钮:

        <script>
          document.querySelectorAll( "[name=update_data], [name=delete_data]" ).forEach( element => {
            var button = element;
            var form = element;
            while ( form.tagName != "FORM" ) {
              form = form.parentElement;
            }
            var method = form.getAttribute( "method" );
            if ( method == "PUT" ) {
              button.addEventListener( "click", putMethod );
            }
            if ( method == "DELETE" ) {
              button.addEventListener( "click", deleteMethod );
            }
          } );
        </script>
        

        对于 PUT 表单上的删除按钮:

        <script>
          document.querySelectorAll( "[name=remove_data]" ).forEach( element => {
            var button = element;
            button.addEventListener( "click", deleteMethod );
        </script>
        

        _ - - - - - - - - - -

        这篇文章https://blog.garstasio.com/you-dont-need-jquery/ajax/对我帮助很大!

        除此之外,您可以设置 postMethod 函数和 getMethod 来处理您喜欢的 POST 和 GET 提交方法,而不是浏览器默认行为。你可以做任何你想做的事情,而不是使用location.reload(),比如显示成功更改或成功删除的消息。

        =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

        JSFiddle:https://jsfiddle.net/enriquerene/d6jvw52t/53/

        【讨论】:

          【解决方案6】:

          根据HTML standard,您可以。 method 属性的唯一有效值是 getpost,对应于 GET 和 POST HTTP 方法。 &lt;form method="put"&gt; 是无效的 HTML,将被视为 &lt;form&gt;,即发送 GET 请求。

          相反,许多框架只是使用 POST 参数来隧道 HTTP 方法:

          <form method="post" ...>
            <input type="hidden" name="_method" value="put" />
          ...
          

          当然,这需要服务器端展开。

          【讨论】:

          • 您一直在链接草稿,而不是最终标准。请注意,稳定的 HTML 版本也不提供它。
          • @hakre HTML5 已经是事实上的标准,并且可能会随着时间的推移而发展。 W3C 所称的“草案”是经过至少 3 年开发的文档,其中浏览器供应商的投入超过 99%,并且已经由他们都永远。但仅针对挑剔者,HTML 4.01 中的here's the equivalent definition(W3C 术语中的技术请求)。
          • 请不要感到被冒犯,我已经写过这只是一个注释和the other HTML versions don't offer it either(XHTML 2 略有例外,但现在这是一个过时的草案)。
          • @hakre 请放心,我一点也不生气。吹毛求疵,我必须评论说 XHTML 在技术上不是 HTML,尽管人们可能会发现一两个相似之处;)
          【解决方案7】:

          不幸的是,现代浏览器不提供对 HTTP PUT 请求的本机支持。要解决此限制,请确保您的 HTML 表单的方法属性为“post”,然后向您的 HTML 表单添加一个方法覆盖参数,如下所示:

          <input type="hidden" name="_METHOD" value="PUT"/>
          

          要测试您的请求,您可以使用 Google chrome 扩展程序“Postman”

          【讨论】:

          • 它应该适用于任何方法,包括 DELETE AND PATCH 等
          【解决方案8】:

          XHTML 1.x 表单仅支持 GET 和 POST。 GET 和 POST 是唯一允许的值 “方法”属性。

          【讨论】:

          【解决方案9】:

          我可以在 html 表单中使用“Put”方法将数据从 HTML 表单发送到服务器吗?

          是的,您可以,但请记住,它不会导致 PUT 而是 GET 请求。如果您对&lt;form&gt; 标签的method 属性使用无效值,浏览器将使用默认值get

          HTML 表单(直到 HTML 版本 4(,5 Draft)和 XHTML 1)仅支持 GET 和 POST 作为 HTTP 请求方法。一种解决方法是使用隐藏的表单字段通过 POST 通过 POST 隧道传输其他方法,该字段由服务器读取并相应地分派请求。 XHTML 2.0 曾经计划支持表单的 GET、POST、PUT 和 DELETE,但它正在进入 HTML5XHTML5,它不打算支持 PUT。 [update to]

          您也可以提供一个表单,但不是提交它,而是使用 JavaScript 的 PUT 方法创建并触发 XMLHttpRequest。

          【讨论】:

          • AJAX 请求不能完全替代表单请求,因为表单请求会将用户重定向到给定资源。例如,目前无法在浏览器中显示路由页面PUT /resource
          • 这样做是个坏主意。框架可以忽略 PUT 的表单参数。 Java 的 HTTPServlet 似乎可以。我们有一个错误,HttpRequest.getParameterMap() 没有返回表单参数。
          • @DaBlick:但不适用于 XMLHttpRequests?如果是这样,那么依赖 fetch API 应该更加标准化。
          猜你喜欢
          • 2011-11-07
          • 1970-01-01
          • 1970-01-01
          • 2018-12-19
          • 1970-01-01
          • 2013-09-07
          • 2021-01-23
          • 1970-01-01
          相关资源
          最近更新 更多