MultipartForm

Build a multipart/form-data body, text fields and files, for an upload or any form post.

Start with MultipartForm.new(), chain AddField and AddFile, then Encode gives the body as one buffer. Send ContentType as the request's Content-Type, read after the last add: a part that holds the boundary makes the form pick a new one. A key is refused as a value: keys go in headers, never in a body.

Example

A form with a fileLuau
--!strict
-- A multipart/form-data body with two fields and a file, as an upload sends it.
local MultipartForm = require("@shotsystem/MultipartForm")

local form = MultipartForm.new()
form:AddField("name", "Apple"):AddField("price", "25")
form:AddFile("notes", "todo.txt", "text/plain", "buy apples")
print(tostring(form))

-- the boundary is random per form: read ContentType after the last Add
local boundary = string.match(form.ContentType, "^multipart/form%-data; boundary=(ShotForm%w+)$")
print("boundary starts with ShotForm:", boundary ~= nil)

-- the body, its boundary shown as BOUNDARY and its CRLF line ends as new lines
local body = buffer.tostring(form:Encode())
body = string.gsub(body, boundary :: string, "BOUNDARY")
for line in string.gmatch(body, "([^\r\n]*)\r\n") do
	print(line)
end
What it printedOutput
MultipartForm(3 parts)
boundary starts with ShotForm: true
--BOUNDARY
Content-Disposition: form-data; name="name"

Apple
--BOUNDARY
Content-Disposition: form-data; name="price"

25
--BOUNDARY
Content-Disposition: form-data; name="notes"; filename="todo.txt"
Content-Type: text/plain

buy apples
--BOUNDARY--

Constructors

NameArgumentsReturnsDescription
MultipartForm.new()MultipartForm

Properties

NameTypeDefaultDescription
ContentTypestringThe Content-Type header to send, boundary included; read it after the last add, since a part holding the boundary makes a new one.

Methods

NameArgumentsReturnsDescription
AddField(name: string, value: string)MultipartFormAdds a plain text field and returns the form, so calls chain; a key is refused as a value, since keys go in headers.
AddFile(name: string, fileName: string, contentType: string, content: buffer | string)MultipartFormAdds a file part with its file name, content type and bytes, and returns the form, so calls chain.
Encode()bufferThe whole body as one buffer, to send with ContentType as its header.