Directly post the upload file in curl not generate Plug.Upload

If I am using the index method to generate a html form in browser and then select file to upload, it will generate the Plug.Upload, but if I directly post the upload file in curl will not generate the Plug.Upload at all. Any idea?

%{
  "_csrf_token" => "TmI-NRw0YwYBFSAwcmocYQAyeT4bJCQr-1tDSNUGnAVrA3OUzU3FLOBc",
  "upload" => %Plug.Upload{
    content_type: "audio/mpeg",
    filename: "music.mp3",
    path: "/var/folders/5s/f43z3rpd4fb1lfm3x647dfx80000gp/T//plug-1602/multipart-1602450255-771991218548719-1"
  }
}

But using curl


curl -v -H "Authorization: Bearer 45ac1JvKsRNky25qnGpC28xAJGvckRXEkzq2a45"  -H "Content-Type: multiform/form-data" -F "name=upload" -F "file=@music_local_cache/music.mp3"   http://localhost:4041/token/token_create

This will give error as the params is %{}

Any idea? thanks.

Maybe the problem is missing csrf token in curl request

I purposely remove the csrf token, I just want another app can post the file upload, and the request header has the Bearer token.

But I do suspect using browser I will get the cookie first and then send the upload.

Here is my pipeline:

  pipeline :browser5 do  ## for token_upload
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
  end

Let me rephrase the question:

  • If I want to upload the file without showing the form first, can I do it?

There are plenty of use cases for this:

  • If want this to be a service that serve other apps and upload the file directly with a token, without human intervention

Also if not using form, can I use JSON API pipeline to upload the file directly?

Looks like this is an unsolvable question :slight_smile:
Here is the discussion already started years ago:

In order to make sure the curl command line is correct, I used the same and test successfully on httpbin.org

curl -v -H "Authorization: Bearer 45ac1JvKsRNky25qnGpC28xAJGvckRXEkzq2a45"  -H "Content-Type: multiform/form-data" -F "name=upload" -F "file=@music_local_cache/music.mp3"   https://httpbin.org/post

Since the curl command is good and can upload a file in one command line, I am thinking maybe I can use Elixir Plug directly to tackle the upload part. But Cowboy give error and not even reach the Plug:

$ curl -v -H "Authorization: Bearer 45ac1JvKsRNky25qnGpC28xAJGvckRXEkzq2a45"  -H "Content-Type: multiform/form-data" -F "name=upload" -F "file=@music_local_cache/music.mp3"   http://localhost:8080/token/token_create
*   Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 8080 failed: Connection refused
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /token/token_create HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
> Authorization: Bearer 45ac1JvKsRNky25qnGpC28xAJGvckRXEkzq2a45
> Content-Length: 300481
> Content-Type: multiform/form-data; boundary=------------------------7bbc66155ea0c6ef
> Expect: 100-continue
>
< HTTP/1.1 415 Unsupported Media Type
< cache-control: max-age=0, private, must-revalidate
< content-length: 20
< date: Wed, 14 Oct 2020 11:23:23 GMT
< server: Cowboy
* HTTP error before end of send, stop sending
<
* Closing connection 0
Something went wrong

JSON API not good enough for this use case, as need to base64 the binary before send.

Good sign: If httpbin.org can do, so Phoenix/Plug/Cowboy !!! :slight_smile:

That should be “multipart/form-data”

There are curl options to do this, FWIW.

Great , solution works!!! :smile:

This is why I so love :love_letter: our community.