Uploading Files with Form Data

Avatar of Hemanta SundarayHemanta Sundaray

Most real-world file upload APIs expect the file as part of a multipart form data body, not as the raw request body. This is because the server often needs additional fields alongside the file: a title, a description, access permissions, and so on.

You can combine files and text fields using FormData:

http.ts
import {
FetchHttpClient,
HttpClient,
HttpClientRequest,
} from "effect/unstable/http";
import { Effect } from "effect";
function uploadAvatar(username: string) {
return Effect.gen(function* () {
const client = yield* HttpClient.HttpClient;
// Create a file (in a browser, this would come from <input type="file">)
const avatarFile = new File(["<fake image bytes>"], "avatar.png", {
type: "image/png",
});
const formData = new FormData();
formData.append("username", username);
formData.append("avatar", avatarFile);
const request = HttpClientRequest.post("https://httpbin.org/post").pipe(
HttpClientRequest.bodyFormData(formData),
);
const response = yield* client.execute(request);
const data = yield* response.json;
return data;
}).pipe(Effect.provide(FetchHttpClient.layer));
}
// Test it
Effect.runPromise(uploadAvatar("emilys")).then((data) => {
console.log("Form fields:", data.form);
console.log("Files:", Object.keys(data.files));
});

Output:

Terminal
Form fields: { username: 'emilys' }
Files: [ 'avatar' ]

The server receives both the text field (username) and the file (avatar) in a single request. The multipart encoding keeps them separate, each with their own content type and metadata.

Sign in to save progress

Stay in the loop

Get notified when new chapters are added and when this course is complete.