hubertlepicki

hubertlepicki

Encoding multipart/form-data HTTP body

Does anyone here know of an Elixir library which would help me assemble bodies of HTTP requests with “multipart/form-data” Content-type?

This would be the reverse of plug/lib/plug/parsers/multipart.ex at v1.8.2 · elixir-plug/plug · GitHub i.e. parsing “multipart/form-data” requests by Plug.

Ideally I could either assemble it and get it as String, or in streaming form (for large file uploads).

Hackney does that and I can try translating that to Elixir, but would be ideal if I didn’t have to for obvious reasons :D.

Does anyone know of a piece of Elixir code that does that, even if it’s part of bigger library?

Most Liked

engineeringdept

engineeringdept

I needed to construct multipart messages recently, but also didn’t want to include Tesla in my dependencies, so I built a separate library for message construction. It should cover most use cases for multipart/form-data requests, but very open to suggestions to improve the API and functionality.

https://github.com/breakroom/multipart

hubertlepicki

hubertlepicki

So the intent behind creating streaming one is that I have to send multipart requests that contain files, and these files can be many megabytes in size. If I do N of these requests at the same time, I could easily end up exhausting my memory quota.

So, the intent was not to make it more performant, but make it not crash production server.

I actually have no idea how the streaming performance versus non-streaming compares. It’d be good test to do.

hubertlepicki

hubertlepicki

I don’t think Finch supports building actual multipart body. This is a task on it’s own.

What I am doing is using Tesla to help me out with that task.

First, build multipart body using Tesla.Multipart

  multipart =                                                                                                           
    Multipart.new()                                                                                                     
    |> Multipart.add_content_type_param("charset=utf-8")                                                                
    |> add_fields(form_data)                                                                                            
    |> add_files(file_parts)                                                                                            
                                                                                                                        
  mp_headers = Multipart.headers(multipart)                                                                             
  stream = Multipart.body(multipart)
  headers = ... # your other headers, optional

And then you can either POST it as a streaming body request, once this PR is merged https://github.com/keathley/finch/pull/107

  :post                                                                                                                 
  |> Finch.build(url, headers ++ mp_headers, {:stream, stream})                                                         
  |> Finch.request(YourFinch) 

Or, you can POSt it in non-streaming fashion (should work on current release/master):

  :post                                                                                                                 
  |> Finch.build(url, headers ++ mp_headers, stream |> Enum.join())                                                         
  |> Finch.request(YourFinch)

Last Post!

simon

simon

A huge thank you for putting multipart together. I’m using the PSPDFKit API in an application where I was already using Finch and it helped me enormously.

Where Next?

Popular in Discussions Top

AstonJ
If a newbie asked you about Phoenix Contexts, how would you explain the basics to them? Feel free to be as concise or in-depth as you li...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 40042 209
New
lucaong
Hello Elixir and Nerves community, I have been working for a while on an open-source embedded key-value database for Elixir, that I call...
230 14350 124
New
Fl4m3Ph03n1x
Background A few days ago I was listening to The future of Elixir from Elixir Talks, with Dave Thomas (@pragdave ) and Brian Mitchell. I...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
cvkmohan
The upcoming Phoenix 1.6 release looks very interesting. Became a habit to watch the commits - and - what they are bringing in. phx.gen...
New

Other popular topics Top

ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 44139 214
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New

We're in Beta

About us Mission Statement