Prepared Uploads
Understand the signed upload instructions returned by prepareUpload().
A prepared upload is the result returned by prepareUpload().
const preparedUpload = await uploader.prepareUpload("avatar", {
filename: "profile.png",
contentType: "image/png",
size: 120_000,
});It contains the instructions the client needs to upload the file directly to the selected provider.
{
strategy: "multipart",
method: "POST",
url: "https://provider.example.com/upload",
headers: {},
fields: {
// Provider-specific signed fields
},
key: "avatars/profile-550e8400-e29b-41d4-a716-446655440000.png",
expiresAt: "2026-07-21T12:00:00.000Z"
}The response shape stays the same across AWS S3 and ImageKit. The returned URL and signed fields depend on the selected provider.
Response fields
| Field | Description |
|---|---|
strategy | How the client should send the upload |
method | The HTTP method to use |
url | The provider endpoint |
headers | Headers required by the request |
fields | Signed multipart form fields |
key | The generated storage key |
expiresAt | When the upload target expires |
strategy
strategy: "multipart"Upload SDK currently prepares multipart form uploads.
The client must create FormData, add every returned field, and then add the file.
Here, multipart means one multipart POST request. It does not mean a chunked or resumable upload.
method
method: "POST"Use the returned HTTP method:
await fetch(preparedUpload.url, {
method: preparedUpload.method,
body: formData,
});Prepared uploads currently use POST.
url
url: "https://provider.example.com/upload"This is the provider endpoint that receives the file.
The exact URL depends on the selected storage profile.
- AWS S3 returns an endpoint for the configured bucket and region.
- ImageKit returns its upload endpoint.
Do not build provider upload URLs manually in client code.
headers
headers: {}Pass the returned headers to fetch():
await fetch(preparedUpload.url, {
method: preparedUpload.method,
headers: preparedUpload.headers,
body: formData,
});The object may be empty.
fields
fields: {
// Provider-specific signed fields
}These are the form fields required by the provider.
They may include:
- A generated key or filename
- A signed policy
- A signature or token
- The declared content type
- Metadata
- Provider-specific settings
The exact field names differ between AWS S3 and ImageKit.
Add every field to FormData without changing it:
const formData = new FormData();
for (const [name, value] of Object.entries(
preparedUpload.fields,
)) {
formData.append(name, value);
}
formData.append("file", file);Changing or removing a signed field can cause the provider to reject the upload.
key
key: "avatars/profile-550e8400-e29b-41d4-a716-446655440000.png"This is the storage key generated by Upload SDK.
It contains the asset's key prefix and the generated filename.
Client filename:
Profile Photo.PNG
Generated key:
avatars/profile-photo-550e8400-e29b-41d4-a716-446655440000.pngUse the key when you need to reference the intended upload location.
expiresAt
expiresAt: "2026-07-21T12:00:00.000Z"This is the time after which the prepared upload should no longer be used.
It is returned as an ISO 8601 date string.
The value comes from the asset's expiresIn configuration and the selected provider's supported limits.
When the target expires, request a new prepared upload.
Do not try to change the expiration or signed fields in the browser.
Uploading the file
Use the prepared upload to create the provider request:
async function uploadToProvider(
file: File,
preparedUpload: PrepareUploadOutput,
): Promise<void> {
const formData = new FormData();
for (const [name, value] of Object.entries(
preparedUpload.fields,
)) {
formData.append(name, value);
}
formData.append("file", file);
const response = await fetch(preparedUpload.url, {
method: preparedUpload.method,
headers: preparedUpload.headers,
body: formData,
});
if (!response.ok) {
throw new Error("The provider rejected the upload.");
}
}The same client flow works with AWS S3 and ImageKit. Only the returned provider values change.
What preparation means
A successful call to prepareUpload() means:
- The selected asset was found.
- The reported file information passed its rules.
- A storage key was generated.
- The provider created a signed upload target.
It does not mean:
- The client uploaded the file.
- The provider accepted the upload.
- The object exists.
- The file contents are valid or safe.
Preparation, upload completion, and file verification are separate stages.
Rules to remember
- Add every returned field to
FormData. - Do not change signed values.
- Use the returned URL, method, and headers.
- Do not manually set the multipart
Content-Type. - Do not reuse an expired target.
- Do not treat
keyas proof of upload. - Keep provider credentials on the server.
Next steps
-
How Uploads Work: See where prepared uploads fit into the full lifecycle.
-
Browser Uploads: Build the complete client-side upload request.
-
API Reference: View the exact
prepareUpload()input and output types.