I am sending binary data to Phoenix via a POST request. I need to download the received data to a file for further processing (untar, run pdflatex, send link back to the pdf file). How do I so the download?
the data comes in from an Elm client, The controller appears to accept the data – no errors – but I don’t see the data when I do IO.inspect params
I might have misunderstood what you are trying to achieve. If you want to upload binary data to a file on the server, https://phoenixframework.org/blog/file-uploads might help. Remember to copy the data from the temporary location provided by Plug as shown in the example.
Yes, I’ve seen that post, but it seems to address a different problem, if I have understood it correctly (uploading a file from one’s computer using a form). I am sending binary data (a tar archive) by http from an Elm app to an Elixir/Phoenix app. The Elm app is sending a POST request with the binary data in the body. I have a dummy controller
def process(conn, params) do
IO.inspect params, label: "params for 'process'"
conn |> render("pdf.json", url: "OK")
end
that receives the data, From the IO.inspect params
line, I know that the client and the server are talking to eachother. But the binary data is not in params
. From what I’ve read, I think one has to use Plug.Parser
, but I am too much of a noob at this point to know what to do.
I guess the real question is how to extract data from the POST request body,
What I need to do is store the binary data in a file, then process it.
Here is what I get on the Elixir side when I make a POST request from the client
[info] OPTIONS /api/print/pdf/harmonic_oscillator!!
[debug] Preflight CORS request from Origin 'http://localhost:8080' is allowed
[info] Sent 200 in 18ms
[info] POST /api/print/pdf/harmonic_oscillator!!
[debug] Simple CORS request from Origin 'http://localhost:8080' is allowed
[debug] Processing with Koko.Web.PrintController.process/2
Parameters: %{"title" => "harmonic_oscillator!!"}
Pipelines: [:api]
params for 'process': %{"title" => "harmonic_oscillator!!"}
[info] Sent 200 in 42ms
Here is the code on the client side that sends the POST request:
sendTarArchiveCmd : String -> List ( String, String ) -> List ( String, Bytes ) -> Cmd DocMsg
sendTarArchiveCmd url stringList dataList =
let
data =
(List.map prepareData dataList) ++ (List.map prepareStringData stringList)
archive : Bytes
archive =
Tar.encodeFiles data |> encode
in
Http.request
{ method = "Post"
, headers = []
, url = url
, body = Http.bytesBody "application/tar" archive
, expect = Http.expectString TexToPdf
, timeout = Nothing
, tracker = Nothing
}
Some progress. I’ve added the line {:ok, body, conn} = Plug.Conn.read_body(conn)
below
def process(conn, params) do
IO.inspect params, label: "params for 'process'"
{:ok, body, conn} = Plug.Conn.read_body(conn)
IO.inspect body, label: "BODY"
conn |> render("pdf.json", url: "OK")
end
Now I am seeing data:
[ debug] Processing with Koko.Web.PrintController.process/2
Parameters: %{“title” => “harmonic_oscillator!!”}
Pipelines: [:api]
params for ‘process’: %{“title” => “harmonic_oscillator!!”}
BODY: <<105, 109, 97, 103, 101, 47, 109, 97, 115, 115, 95, 115, 112, 114, 105, 110,
103, 45, 102, 100, 97, 99, 46, 112, 110, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …>>
[info] Sent 200 in 7ms
OK, its saving the POSTed data to file now:
def process(conn, params) do
IO.inspect params, label: "params for 'process'"
{:ok, body, conn} = Plug.Conn.read_body(conn)
IO.inspect body, label: "BODY"
{:ok, file} = File.open "tarfileXXX.tar", [:write]
IO.binwrite file, body
File.close file
conn |> render("pdf.json", url: "OK")
end
More work to do, but this was the blocker