Uploading File using Axios via Multipart

interop

#1

I’m attempting to upload a file using axios. Right now I’m encoding the file as a Js object as such:

  let file = Belt.Array.getExn(files, 0);
  let headers =
    Js.Dict.(
      {
        let dict = empty();
        dict->set("Content-type", "multipart/form-data");
        dict;
      }
    );
  let headers = Axios.Headers.fromDict(headers);
  Js.Promise.(
    Axios.postDatac(Utils.apiUrl ++ "/media", file, Axios.makeConfig(~headers, ()))
    |> then_(response => resolve(Js.log(response##data)))
    |> catch(err => resolve(Js.log(err)))
    |> ignore
  );
  ();

I’m using an explicit headers because Axios doesn’t infer that this should be a multipart, but instead labels it as application/x-www-form-urlencoded. However, I also need a boundary header, but I can’t manually add that. How can I get Axios to figure out the boundary properly?

Sidenote, I was originally using bs-webapi, but I don’t think bs-webapi’s bindings for the File API plays well with bs-axios. Is there a way to get them to work together?

Thanks,
Nicholas


#2

Couldn’t you try something like this?

dict->set("Content-type", "multipart/form-data; boundary=--yourBoundaryValue");

I had implemented file upload using bs-axios before Js.Dict was introduced like so:

let instance =
                  Axios.Instance.create(
                    Axios.makeConfig(
                      ~baseURL="/api",
                      ~headers={
                        "Content-Type": "multipart/form-data; boundary=--salamalaykum",
                      },
                      (),
                    ),
                  );

#3

I’m trying to avoid setting my own boundary, since I don’t actually know if it’s valid.


#4

Is this a language-specific question or library-specific question?

In other words, are you asking how to do this in Reason, or how to do it in general in Axios?


#5

Well, I wouldn’t be asking on a Reason forum if this was an Axios question :stuck_out_tongue:. All kidding aside, Axios does this by default if you pass it a FormData with a File object inside. The issue I’m having is mimicking these Web API types inside Reason. Something like bs-webapi isn’t made to work well with bs-axios.

Thanks for the response!


#6

Normally, the way we use various libraries in Reason is almost exactly the same way we do in JavaScript, just with more type-safety idioms. So if you’d give Axios a FormData object containing a File object in JavaScript, you just need to figure out a way to do the same thing in Reason. The difficulty here is that we don’t have FormData bindings in bs-webapi right now (there’s an open issue). Normally we get a FormData object when it is passed in to an onSubmit event handler.

For example, if you’re using ReasonReact and you have a form with an onSubmit handler, the event it will get is of type ReactEvent.Form.t, from which you can get the form object itself using the ReactEvent.Form.target(formEvent) function. You pass this form object into a FormData constructor call (which you will need to bind to yourself, but it’s pretty simple), and get a formData object. Then you pass this as the data argument to a bs-axios request.

You can use this JavaScript equivalent to guide your work: https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects#Sending_files_using_a_FormData_object