最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - FormData textarea puts r (carriage return) when sent with POST - Stack Overflow

programmeradmin0浏览0评论

Why does FormData insert carriage returns before line feed characters?

When I send post request with FormData, it uses CRLF line endings, even though the value of textarea has no carriage returns at all. This makes my character length validation fail unexpectedly.

The sample code below shows the difference between the textarea string value, the data in FormData and the encoded data that will get submitted. JSON.stringify() is used to escape the control characters.

document.getElementById('HistoryValue').textContent = JSON.stringify(document.forms.CRLFSample.history.value);
const fd = new FormData(document.forms.CRLFSample);
document.getElementById('FormData').textContent = JSON.stringify(fd.get('history'));
new Response(fd).text().then(text =>
document.getElementById('POSTData').textContent = JSON.stringify(text));
#CRLFSample {
  width: 90%;
}
<form id="CRLFSample" method="POST">
  <textarea name="history">
    line 1
    line 2
  </textarea>
</form>
<dl>
<dt>Textarea</dt><dd id="HistoryValue"></dd>
<dt>FormData</dt><dd id="FormData"></dd>
<dt>POST data</dt><dd id="POSTData"></dd>
</dl>

Why does FormData insert carriage returns before line feed characters?

When I send post request with FormData, it uses CRLF line endings, even though the value of textarea has no carriage returns at all. This makes my character length validation fail unexpectedly.

The sample code below shows the difference between the textarea string value, the data in FormData and the encoded data that will get submitted. JSON.stringify() is used to escape the control characters.

document.getElementById('HistoryValue').textContent = JSON.stringify(document.forms.CRLFSample.history.value);
const fd = new FormData(document.forms.CRLFSample);
document.getElementById('FormData').textContent = JSON.stringify(fd.get('history'));
new Response(fd).text().then(text =>
document.getElementById('POSTData').textContent = JSON.stringify(text));
#CRLFSample {
  width: 90%;
}
<form id="CRLFSample" method="POST">
  <textarea name="history">
    line 1
    line 2
  </textarea>
</form>
<dl>
<dt>Textarea</dt><dd id="HistoryValue"></dd>
<dt>FormData</dt><dd id="FormData"></dd>
<dt>POST data</dt><dd id="POSTData"></dd>
</dl>

The above has been tested in Firefox 92-94 and Chrome 95 on macOS 10.14 & 12 and Android 10. Note "Textarea" shows "\n" for newlines, but "POSTData" has "\r\n". "FormData" shows different results depending mostly on the browser, with most versions of FireFox showing just "\n" and most versions of Chrome showing "\r\n".

Edited by original asker below

Didn't think I had this many ments. Thank you for your interests, and allow me to apologize for not observing site guide lines. I'll try to elaborate more to best help you to reproduce the error and understand what's going on.

I tested this on my mac Catalina 10.15.7 and my browser is chrome Version 95.0.4638.69 (Official Build) (x86_64).

Below is my attempt to validate char length with formdata and just grabbing value of textarea respectively.

let formData = new FormData(document.getElementById('form'));
let historyEl = document.getElementById('id_history');
console.log(formData.get('history').length, formData.get('history').includes('\r\n'));
console.log(historyEl.value.length, historyEl.value.includes('r\n'));
<form id="form" method="POST">
<textarea class="materialize-textarea" cols="40" name="history" id="id_history" rows="10">    Lorem Ipsum is simply dummy text of the printing and typesetting 
industry. 
Lorem Ipsum has been the industry's standard dummy text ever since 
the 1500s, 
when an unknown printer took a galley of type and scrambled it to 
make a type 
specimen book. It has survived not only five centuries, but also 
the leap into electronic 
typesetting, remaining essentially unchanged. It was popularised in 
the 190
.</textarea>
</form>

As you can see by running code snippet, formdata length of history shows different length than that of textarea element value.

Originally I received the textarea value from Window user, and I thought it was only the matter of OS. But when I inspected it, that even happens in my OS, especially when submitting with form data.

One might ask that I can inspect length of textarea value, but I try to avoid that because checking with formdata is the whole point of frontend validation.

I'm not native English speaker, and my char length validation was on other non latin language, but something prevents me from posting non-latin language in code snippet. But Since console yields different lengths respectively, I believe you'll get the idea with other chars anyway.

Share Improve this question edited Nov 5, 2021 at 1:47 harryghgim asked Nov 4, 2021 at 7:36 harryghgimharryghgim 1,5704 gold badges15 silver badges39 bronze badges 12
  • Can you share your areatext html ? And the JS coder that belongs to the question? – Maik Lowrey Commented Nov 4, 2021 at 7:43
  • I've edited the question for reproduction. – harryghgim Commented Nov 4, 2021 at 8:07
  • thanks. i updated my answear. tell me if it useful for you. – Maik Lowrey Commented Nov 4, 2021 at 8:24
  • It used to be specified that textarea's value for form submission should be normalized with CRLF, but since github./whatwg/html/pull/6697 that should be LF only now, quite weird browsers didn't catch up... – Kaiido Commented Nov 4, 2021 at 9:03
  • 1 @outis here is a repro: jsfiddle/9zd6qpk1 happens in both FF and Chrome on my macOS system. – Kaiido Commented Nov 4, 2021 at 13:11
 |  Show 7 more ments

2 Answers 2

Reset to default 9

According to MDN, FormData uses the "multipart/form-data" format, specified by RFC 2388, section 3 of which states:

The media-type multipart/form-data follows the rules of all multipart MIME data streams as outlined in RFC 2046.

RFC § 4.1.1, the section on line endings, states:

The canonical form of any MIME "text" subtype MUST always represent a line break as a CRLF sequence.

Which is why line endings get encoded as CRLF when posted. What is not clear from this is whether line endings should be encoded as CRLF in FormData's entries (such as shown by the result of formData.get('history')).

The spec for FormData makes no mention of encoding line endings when adding an entry or value. The only processing of a value when being added is for Blob (i.e. binary) and File objects. No processing of the value by FormData.get() is mentioned. A strict reading of this would be that Chrome's behavior (encoding values stored in FormData) is non-standard. However, storing a value directly would mean that the browser's internal (likely the platform's) line ending encoding would be used, which might vary.

The Fetch standard designates Response as being responsible for handling the multipart/form-data encoding; specifically, extracting FormData is supposed to use the "multipart/form-data" encoding algorithm.

You have linebreaks inside your textarea. I can think of two ways to avoid this problem. I am sure there are several other possibilities.

In this case you can collect the data and remove/replace the \n \r 's with a js replace function. like so:

const text = fd.get('history')
console.log('out1:',text)
console.log('out2:', text.replace(/(\r\n|\n|\r)/gm, ""));

Or you add a eventlistener to the textarea which recognises that a return has been entered and deletes it immediately.

document.querySelector('textarea[name=history]').onkeydown = function( e ) {
  if (e.keyCode == 13 && !e.shiftKey)
  {      
      e.preventDefault();
      console.log('your code to remove immediately the line break/return')
  }    
}
发布评论

评论列表(0)

  1. 暂无评论