ใช้วิธี PUT ในรูปแบบ HTML


175

ฉันสามารถใช้วิธี PUT ในรูปแบบ HTML เพื่อส่งข้อมูลจากแบบฟอร์มไปยังเซิร์ฟเวอร์ได้หรือไม่

คำตอบ:


128

XHTML 1.x ฟอร์มสนับสนุน GET และ POST เท่านั้น GET และ POST เป็นค่าที่ใช้ได้สำหรับแอตทริบิวต์ "method" เท่านั้น


5
XHTML ค่อนข้างล้าสมัย ยังดูเหมือนว่าค่าสองค่าเดียวกันนั้นจะใช้ได้ใน html5 developer.mozilla.org/en-US/docs/Web/HTML/Element/…
jakubiszon

194

ตามที่มาตรฐาน HTMLคุณสามารถไม่ได้ ค่าที่ใช้ได้เฉพาะสำหรับแอตทริบิวต์ method คือgetและpostสอดคล้องกับวิธี GET และ POST HTTP <form method="put">HTML ไม่ถูกต้องและจะถือว่าเป็น<form>เช่นส่งคำขอ GET

แต่เฟรมเวิร์กจำนวนมากใช้พารามิเตอร์ POST เพื่อสร้างช่องสัญญาณวิธี HTTP:

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

แน่นอนว่าต้องมีการเปิดเครื่องฝั่งเซิร์ฟเวอร์


3
คุณได้ทำการเชื่อมโยงร่างไม่ใช่มาตรฐานขั้นสุดท้าย เพียงสังเกตเวอร์ชัน HTML ที่เสถียรไม่ได้เสนอให้เช่นกัน
hakre

13
@hakre HTML5 เป็นมาตรฐาน de-พฤตินัยแล้วและอาจมีการพัฒนาอยู่ตลอดเวลา สิ่งที่ W3C เรียกว่า "แบบร่าง" นั้นได้รับการพัฒนาเป็นเอกสารอย่างน้อย 3 ปีโดยมีการป้อนข้อมูลของผู้ขายเบราว์เซอร์มากกว่า> 99% และมีการนำไปใช้งานแล้ว (อย่างน้อยที่สุดก็เป็นเรื่องนี้ ทั้งหมดของพวกเขาตลอดไป แต่สำหรับ nitpickers นี่คือคำจำกัดความเทียบเท่าใน HTML 4.01 (คำขอทางเทคนิคในเงื่อนไขของ W3C)
Phihag

โปรดอย่ารู้สึกขุ่นเคืองฉันเขียนไปแล้วว่าเป็นเพียงโน้ตและHTML เวอร์ชันอื่นไม่ได้ให้บริการด้วย (ยกเว้น XHTML 2 เล็กน้อย แต่ตอนนี้เป็นฉบับร่างที่ล้าสมัยแล้ว)
hakre

1
@ ฮาเครมั่นใจได้ว่าฉันไม่ได้โกรธอะไรเลย nitpicking nitpicker ที่ฉันต้องแสดงความคิดเห็นว่า XHTML เป็นเทคนิคที่ไม่ HTML, ถึงแม้คนหนึ่งอาจพบหนึ่งหรือสองคล้ายคลึงกัน;)
phihag

44

ฉันสามารถใช้วิธี "Put" ในรูปแบบ html เพื่อส่งข้อมูลจากแบบฟอร์ม HTML ไปยังเซิร์ฟเวอร์ได้หรือไม่

ใช่คุณทำได้ แต่โปรดจำไว้ว่ามันจะไม่ส่งผลให้เกิด PUT แต่เป็นคำขอ GET ถ้าคุณใช้ค่าไม่ถูกต้องสำหรับmethodแอตทริบิวต์ของแท็กเบราเซอร์จะใช้ค่าเริ่มต้น<form>get

รูปแบบ HTML (สูงสุด HTML เวอร์ชัน 4 (, 5 Draft) และ XHTML 1) รองรับ GET และ POST เป็นวิธีการร้องขอ HTTP เท่านั้น วิธีหลีกเลี่ยงปัญหานี้คือการขุดอุโมงค์วิธีอื่น ๆ ผ่าน POST โดยใช้ฟิลด์แบบฟอร์มที่ซ่อนอยู่ซึ่งเซิร์ฟเวอร์อ่านและการร้องขอที่ส่งไป XHTML 2.0เคยวางแผนที่จะสนับสนุน GET, POST, PUT และ DELETE สำหรับแบบฟอร์ม แต่มันจะเป็นXHTML5ของHTML5ซึ่งไม่ได้วางแผนที่จะสนับสนุน PUT [อัปเดตเป็น]

คุณสามารถเสนอแบบฟอร์ม แต่แทนที่จะส่งให้สร้างและเรียกใช้ XMLHttpRequest โดยใช้วิธี PUT พร้อม JavaScript



การร้องขอ AJAX ไม่สามารถแทนที่การร้องขอแบบฟอร์มได้อย่างสมบูรณ์เนื่องจากการร้องขอแบบฟอร์มเปลี่ยนเส้นทางผู้ใช้ไปยังทรัพยากรที่กำหนด ตัวอย่างเช่นมีวิธีใด ณ PUT /resourceตอนนี้ที่จะแสดงในเบราว์เซอร์หน้าของเส้นทาง
JacopoStanchi

เป็นความคิดที่ดีที่จะทำสิ่งนี้ กรอบงานสามารถละเว้นพารามิเตอร์แบบฟอร์มสำหรับ PUT HTTPServlet ของ Java น่าจะเป็น เรามีข้อผิดพลาดที่HttpRequest.getParameterMap()ไม่ได้ส่งคืนพารามิเตอร์แบบฟอร์ม
DaBlick

@DaBlick: แต่ไม่ใช่สำหรับ XMLHttpRequests ใช่ไหม ถ้าเป็นเช่นนั้นการใช้ API การดึงข้อมูลควรเป็นมาตรฐานมากขึ้น
hakre

27

_method วิธีแก้ปัญหาฟิลด์ที่ซ่อนอยู่

เทคนิคง่าย ๆ ต่อไปนี้ถูกใช้โดยเฟรมเวิร์กเว็บบางตัว:

  • เพิ่ม_methodพารามิเตอร์ที่ซ่อนอยู่ให้กับฟอร์มใด ๆ ที่ไม่ใช่ GET หรือ POST:

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

    สิ่งนี้สามารถทำได้โดยอัตโนมัติในเฟรมเวิร์กผ่านเมธอดตัวช่วยสร้าง HTML

  • แก้ไขวิธีการแบบฟอร์มจริงเพื่อ POST ( <form method="post")

  • ประมวลผล_methodบนเซิร์ฟเวอร์และทำตามราวกับว่าวิธีนั้นได้ถูกส่งแทนที่จะเป็น POST จริง

คุณสามารถทำได้ใน:

  • Rails: form_tag
  • Laravel: @method("PATCH")

เหตุผล / ประวัติว่าทำไมจึงเป็นไปไม่ได้ใน pure HTML: /software/114156/why-there-are-no-put-and-delete-methods-in-html-forms


Laravel (php) มีคุณสมบัติเดียวกันโดยใช้@method("PATCH")
santiago arizti

ดูเหมือนว่าการแก้ไขปัญหาที่สมเหตุสมผล แต่ก็ยังโชคร้ายเนื่องจากทำให้การดีบักยาก ตัวอย่างเช่นหากคุณต้องผ่านบันทึกเซิร์ฟเวอร์หรือทำการวิเคราะห์เครือข่ายเพื่อตรวจสอบบางสิ่งคุณจะไม่เห็นผลลัพธ์ที่ถูกต้องเนื่องจากวิธีการ HTTP ที่ใช้ในส่วนหัว HTTP นั้นยังคงPOSTไม่ใช่สิ่งที่คุณต้องการจริงๆ
code_dredd

8

น่าเสียดายที่เบราว์เซอร์ที่ทันสมัยไม่ได้ให้การสนับสนุนเนทีฟสำหรับคำขอ HTTP PUT หากต้องการแก้ไขข้อ จำกัด นี้โปรดตรวจสอบให้แน่ใจว่าแอตทริบิวต์ของแบบฟอร์ม HTML ของคุณคือ“ โพสต์” จากนั้นเพิ่มพารามิเตอร์การแทนที่เมธอดลงในแบบฟอร์ม HTML ของคุณดังนี้:

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

ในการทดสอบคำขอของคุณคุณสามารถใช้ "บุรุษไปรษณีย์" ส่วนขยายของ Google Chrome


1
มันควรจะใช้ได้กับวิธีการใด ๆ รวมถึงการลบและ
แพทช์

1

ในการตั้งค่าวิธีการ 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/

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.