Sử dụng phương pháp PUT ở dạng HTML


175

Tôi có thể sử dụng phương thức PUT trong biểu mẫu HTML để gửi dữ liệu từ biểu mẫu đến máy chủ không?

Câu trả lời:



194

Theo tiêu chuẩn HTML , bạn không thể . Các giá trị hợp lệ duy nhất cho thuộc tính phương thức là getpost, tương ứng với các phương thức GET và POST HTTP. <form method="put">là HTML không hợp lệ và sẽ được xử lý như thế <form>, tức là gửi yêu cầu GET.

Thay vào đó, nhiều khung công tác chỉ cần sử dụng tham số POST để tạo đường hầm cho phương thức HTTP:

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

Tất nhiên, điều này đòi hỏi phải mở ra phía máy chủ.


3
Bạn đã được liên kết một dự thảo, không phải là một tiêu chuẩn cuối cùng. Chỉ cần lưu ý, các phiên bản HTML ổn định cũng không cung cấp nó.
hakre

13
@hakre HTML5 là tiêu chuẩn không chính thức và có thể sẽ phát triển theo thời gian. Cái mà W3C gọi là "Bản nháp" là một tài liệu được phát triển trong ít nhất 3 năm với đầu vào của các nhà cung cấp trình duyệt với hơn> 99% và đã được triển khai (ít nhất là khi nói đến phần này và hầu hết các phần không bí truyền) bởi tất cả chúng mãi mãi Nhưng chỉ dành cho nitopperers, đây là định nghĩa tương đương trong HTML 4.01 (Yêu cầu kỹ thuật theo thuật ngữ của W3C).
phihag

Xin đừng cảm thấy bị xúc phạm, tôi đã viết rằng đó chỉ là một ghi chú và các phiên bản HTML khác cũng không cung cấp nó (ngoại trừ một chút XHTML 2, nhưng bây giờ đó là một bản nháp lỗi thời).
hakre

1
@hakre Hãy yên tâm tôi không bị xúc phạm chút nào. Đánh lừa nitpicker, tôi phải nhận xét rằng XHTML về mặt kỹ thuật không phải là HTML, mặc dù người ta có thể tìm thấy một hoặc hai điểm tương đồng;)
phihag

44

Tôi có thể sử dụng phương thức "Đặt" ở dạng html để gửi dữ liệu từ Biểu mẫu HTML đến máy chủ không?

Có, bạn có thể, nhưng hãy nhớ rằng nó sẽ không dẫn đến PUT mà là yêu cầu NHẬN. Nếu bạn sử dụng giá trị không hợp lệ cho methodthuộc tính của <form>thẻ, trình duyệt sẽ sử dụng giá trị mặc định get.

Các biểu mẫu HTML (tối đa HTML phiên bản 4 (, 5 Bản nháp) và XHTML 1) chỉ hỗ trợ GET và POST dưới dạng phương thức yêu cầu HTTP. Một cách giải quyết cho vấn đề này là tạo đường hầm cho các phương thức khác thông qua POST bằng cách sử dụng trường biểu mẫu ẩn được đọc bởi máy chủ và yêu cầu được gửi đi tương ứng. XHTML 2.0 từng được lên kế hoạch để hỗ trợ GET, POST, PUT và DELETE cho các biểu mẫu, nhưng nó sẽ đi vào XHTML5 của HTML5 , không có kế hoạch hỗ trợ PUT. [Cập nhật lên]

Ngoài ra, bạn có thể cung cấp một biểu mẫu, nhưng thay vì gửi nó, hãy tạo và kích hoạt XMLHttpRequest bằng phương thức PUT với JavaScript.



Yêu cầu AJAX không thể thay thế hoàn toàn yêu cầu biểu mẫu vì yêu cầu biểu mẫu chuyển hướng người dùng đến tài nguyên đã cho. Ví dụ, hiện tại không có cách nào để hiển thị trên trình duyệt trang của tuyến đường PUT /resource.
JacopoStanchi

Đó là một ý tưởng tồi để làm điều này. Các khung có thể bỏ qua các tham số biểu mẫu cho PUT. HTTPServlet của Java dường như. Chúng tôi đã có một lỗi mà HttpRequest.getParameterMap()không trả về các tham số hình thức.
DaBlick

@DaBlick: Nhưng không phải cho XMLHttpRequests? Nếu vậy thì việc dựa vào API tìm nạp sẽ được chuẩn hóa hơn.
hakre

26

_method ẩn trường giải pháp

Kỹ thuật đơn giản sau đây được sử dụng bởi một vài khung web:

  • thêm một _methodtham số ẩn vào bất kỳ dạng nào không phải là GET hoặc POST:

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

    Điều này có thể được thực hiện tự động trong các khung thông qua phương thức trợ giúp tạo HTML.

  • sửa phương thức biểu mẫu thực tế thành POST ( <form method="post")

  • xử lý _methodtrên máy chủ và thực hiện chính xác như thể phương thức đó đã được gửi thay vì POST thực tế

Bạn có thể đạt được điều này trong:

  • Đường ray: form_tag
  • Ấu trùng: @method("PATCH")

Lý do / lịch sử tại sao không thể có trong HTML thuần túy: /software/114156/why-there-are-no-put-and-delete-methods-in-html-forms


Laravel (php) có tính năng tương tự bằng cách sử dụng@method("PATCH")
santiago arizti

Nó có vẻ như một cách giải quyết hợp lý, nhưng vẫn không may, vì nó làm cho việc gỡ lỗi trở nên khó khăn. Ví dụ: nếu bạn cần thông qua nhật ký máy chủ hoặc phân tích mạng để xác minh một số thứ, bạn sẽ không thấy đầu ra chính xác, vì phương thức HTTP được sử dụng trong các tiêu đề HTTP vẫn còn POSTvà không phải là những gì bạn thực sự cần.
code_dredd

8

Thật không may, các trình duyệt hiện đại không cung cấp hỗ trợ riêng cho các yêu cầu HTTP PUT. Để khắc phục giới hạn này, hãy đảm bảo thuộc tính phương thức của biểu mẫu HTML của bạn là Đăng bài, sau đó thêm tham số ghi đè phương thức vào biểu mẫu HTML của bạn như sau:

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

Để kiểm tra yêu cầu của bạn, bạn có thể sử dụng "Người đưa thư" một tiện ích mở rộng của Google chrome


1
Nó nên hoạt động cho bất kỳ phương pháp nào, bao gồm XÓA VÀ ĐÁNH GIÁ, v.v.
Tofeeq

1

Để thiết lập các phương thức PUT và DELETE tôi thực hiện như sau:

<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>

Sau đó, JS hành động để thực hiện các phương thức mong muốn:

<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>

Với các hàm này được xác định, tôi thêm một trình lắng nghe sự kiện vào các nút tạo yêu cầu phương thức biểu mẫu:

<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>

Và đối với nút loại bỏ trên biểu mẫu PUT:

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

_ - - - - - - - - - - -

Bài viết này https://blog.garstasio.com/you-dont-need-jquery/ajax/ giúp tôi rất nhiều!

Ngoài ra, bạn có thể đặt chức năng postMethod và getMethod để xử lý các phương thức gửi POST và GET theo ý muốn thay vì hành vi mặc định của trình duyệt. Bạn có thể làm bất cứ điều gì bạn muốn thay vì sử dụng location.reload(), như hiển thị thông báo về những thay đổi thành công hoặc xóa thành công.

= = = = = = = = =

Mã thông báo: https://jsfiddle.net/enriquerene/d6jvw52t/53/

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.