1

I tried to search for solution (for 2 days now) bot nothing helps me.

Because of many reasons I was forced to write own library in JavaScript to build a multipart/dorm-data body.

I checked how other libraries (for node) works and I read the spec. Then I wrote the code (https://github.com/jarrodek/ChromeRestClient/blob/files/app/elements/payload-editor/multipart-form-data.js) which is quite simple because the spec is.

However, my test server do not recognise parameters in the request. Any parameters (text or files).

My library generates generating the following HTTP message:

([NL] represents new line character which is \r\n)

POST /post HTTP/1.1[NL]
HOST: localhost:8081[NL]
content-type: multipart/form-data; boundary=-------------805520824430161118507807[NL]
content-length: 17789[NL]

-------------805520824430161118507807[NL]
Content-Disposition: form-data; name="image"; filename="arc-icon.png"[NL]
Content-Type: image/png[NL]
[NL]
�PNG[NL]
[binary data for about ~17700 bytes)[NL]
[NL]
-------------805520824430161118507807--[NL]

This is snapshot what is actually passed to a socket. The library builds the HTTP message and converts it into the ArrayBuffer which is an argument in socket send function.

Now, I know there's some issue with my code, I just can't find it. I tried to add new line after message part (as in the code above) or not (after image data I always adding new line). Maybe someone can see an issue with the message here and point it out because I have no more ideas how to fix it :)

19
  • "The library builds the HTTP message and converts it into the ArrayBuffer which is an argument in socket send function" Where is ArrayBuffer at javascript at Question? "However, my test server do not recognise parameters in the request" Can you include full javascript at Question and reproduce issue at jsfiddle jsfiddle.net or plnkr plnkr.co? Commented Feb 3, 2017 at 21:30
  • It actually doesn't matter. The HTTP message in the question is converted to string message sent to server. I need to find an issue with the HTTP message to correct error in code. Analysing the code would much more difficult than the message (in this case) Commented Feb 3, 2017 at 21:33
  • Why can you not use FormData? Commented Feb 3, 2017 at 21:34
  • I can't use any of this services because it's a chrome app that is using sockets API which isn't available in regular JS API. Like I said, I need to find an issue with the message, not the code. However, full code is linked in the question - @guest271314 Commented Feb 3, 2017 at 21:35
  • 1
    Not sure how I can get HTTP body message from FormData :) I can only do it using Fetch API and the request object. But I can't until bugs.chromium.org/p/chromium/issues/detail?id=688100 is fixed - @guest271314 Commented Feb 3, 2017 at 21:46

2 Answers 2

1

Finally found it. The issue was with the boundary. According to spec body parts are separated from each other with two dash (-) signs and the boundary string defined in content type. This two dashes missing in my message.

So the correct version of the message body is:

POST /post HTTP/1.1[NL]
HOST: localhost:8081[NL]
content-type: multipart/form-data; boundary=-------------805520824430161118507807[NL]
content-length: 17789[NL]

---------------805520824430161118507807[NL]
Content-Disposition: form-data; name="image"; filename="arc-icon.png"[NL]
Content-Type: image/png[NL]
[NL]
�PNG[NL]
[binary data for about ~17700 bytes)[NL]
[NL]
---------------805520824430161118507807--[NL]
Sign up to request clarification or add additional context in comments.

Comments

0

Not sure how I can get HTTP body message from FormData :) I can only do it using Fetch API and the request object.

You can iterate FormData object, call .blob(), first, then pass Blob to new Response() with .arrayBuffer() chained.

<input name="files" type="file" accepts="image/*" multiple="multiple">
<script>
  document.querySelector("input[type=file]")
    .onchange = (e) => {
      const [files, fd, arr] = [e.target.files, new FormData(), Array()];

      for (let file of files) {
        console.log(file);
        fd.append(`file-${[...fd.keys()].length}`, file, file.name);
      }

      for (let [prop] of fd) {
        let request = new Request("/", {
          method: "POST",
          body: fd.get(prop)
        });
        arr.push(
          request.blob()
          .then(blob => new Response(blob).arrayBuffer())
        )
      }

      Promise.all(arr)
        .then(buffers => {
          for (let ab of buffers) {
            console.log(ab);
            let img = new Image;
            img.onload = () => {
              document.body.appendChild(img)
            }
            let url = URL.createObjectURL(new Blob([ab]));
            img.src = url;
          }
        })
    }
</script>

To read "multipart/form-data" use .text() chained to Request() then parse returned data using String or RegExp methods.

11 Comments

You are right and this is what I did before. But in Chrome 56 there is a bug repoted by me earlier this week ( bugs.chromium.org/p/chromium/issues/detail?id=688100) that makes this impossible. And you don't need to iterate over FormData because the Request object can accept FormData and the arrayBuffer function produces with full multipart message body. But because of this bug I can't use it. So I'm looking for different way.
@PawełPsztyć "But in Chrome 56 there is a bug repoted by me earlier this week ( bugs.chromium.org/p/chromium/issues/detail?id=688100) that makes this impossible." Not sure what you mean by "impossible"? Does javascript at Answer not return expected result? Not sure that the result is a bug.
Your answer do not answers my question. The problem is not with creating ArrayBuffer from file. The question is about producing valid multipart message from form data.
You can use fetch, Request or Response to create a valid multipart/form-data message, as demonstrated at Answer and linked Questions.
Why can you not use fetch where bug report uses Request?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.