fastify-xstorage
upload / uploadMultiple
Upload one file or multiple files concurrently to S3-compatible storage with auto-naming, folder prefix, and MIME type detection.
upload / uploadMultiple
Upload a single file or multiple files concurrently to S3-compatible storage. Keys are auto-generated with a random 8-byte hex suffix to avoid collisions unless you supply an explicit key.
Signatures
fastify.xStorage.upload(
file: Buffer | Stream,
filename: string,
options?: {
folder?: string;
key?: string;
contentType?: string;
metadata?: Record<string, string>;
useRandomName?: boolean;
acl?: string;
}
): Promise<{ key: string; url: string; size: number | null; contentType: string; bucket: string }>
fastify.xStorage.uploadMultiple(
files: Array<{ file: Buffer; filename: string; acl?: string }>,
options?: {
folder?: string;
contentType?: string;
metadata?: Record<string, string>;
useRandomName?: boolean;
acl?: string;
}
): Promise<Array<{ key: string; url: string; size: number | null; contentType: string; bucket: string }>>
Params
upload
| Name | Type | Required | Description |
|---|---|---|---|
file | Buffer | Stream | Yes | File content. |
filename | string | Yes | Original filename — used for extension and MIME type detection. |
options.folder | string | No | Prefix folder (e.g., "avatars"). Prepended to the generated key. |
options.key | string | No | Explicit storage key. Overrides auto-generation entirely. |
options.contentType | string | No | MIME type override. Auto-detected from extension if omitted. |
options.metadata | object | No | Custom S3 metadata key-value pairs. |
options.useRandomName | boolean | No | Append random hex suffix to avoid collisions. Default true. |
options.acl | string | No | Per-file ACL. Falls back to plugin-level acl. |
uploadMultiple
| Name | Type | Required | Description |
|---|---|---|---|
files | array | Yes | Non-empty array of { file, filename, acl? } objects. |
options | object | No | Shared options applied to all files (same shape as upload options). |
Returns
| Field | Type | Description |
|---|---|---|
key | string | The storage key of the uploaded file. |
url | string | Full public URL (publicUrl + "/" + key). |
size | number | null | File size in bytes; null for stream inputs. |
contentType | string | MIME type used for the upload. |
bucket | string | Name of the S3 bucket. |
Throws
[xStorage] file is required for upload— iffileis falsy.[xStorage] filename is required and must be a string— iffilenameis missing.[xStorage] files must be a non-empty array— iffilesis empty or not an array.[xStorage] Failed to upload file "<key>": <message>— if the S3 PUT fails.
Examples
upload — single file with folder prefix
const buffer = fs.readFileSync("./photo.jpg");
const result = await fastify.xStorage.upload(buffer, "photo.jpg", {
folder: "avatars",
});
console.log(result.url); // https://cdn.example.com/avatars/photo-a1b2c3d4e5f6.jpg
console.log(result.key); // avatars/photo-a1b2c3d4e5f6.jpg
upload — explicit key, public ACL
const result = await fastify.xStorage.upload(logoBuffer, "logo.png", {
key: "brand/logo.png",
contentType: "image/png",
acl: "public-read",
});
uploadMultiple — concurrent batch upload
const files = [
{ file: coverBuffer, filename: "cover.jpg" },
{ file: backBuffer, filename: "back.jpg" },
];
const results = await fastify.xStorage.uploadMultiple(files, {
folder: "products/book-123",
});
console.log(results.length); // 2
Realistic — multipart file upload handler
fastify.post("/media/upload", async (request, reply) => {
const parts = request.files();
const uploads = [];
for await (const part of parts) {
const buffer = await part.toBuffer();
uploads.push({ file: buffer, filename: part.filename });
}
const results = await fastify.xStorage.uploadMultiple(uploads, {
folder: `users/${request.user.id}/media`,
});
await db.media.bulkInsert(
results.map((r) => ({
userId: request.user.id,
key: r.key,
url: r.url,
size: r.size,
contentType: r.contentType,
}))
);
return reply.send({ uploaded: results.length });
});
See also
- delete / deleteMultiple — remove uploaded files
- getSignedUploadUrl — let clients upload directly to S3, bypassing your server
- getMetadata — read content type, size, and custom metadata after upload
AI Context
package: "@xenterprises/fastify-xstorage"
methods: fastify.xStorage.upload(file, filename, options?) | fastify.xStorage.uploadMultiple(files, options?)
use-when: Upload one or multiple files to S3-compatible storage with auto key generation, folder prefix, and MIME detection
returns: { key, url, size, contentType, bucket }
getSignedUrl / getSignedUploadUrl / getPublicUrl
Generate temporary signed download URLs, presigned direct-upload URLs, or compute a synchronous public URL.
fastify-xwhatconverts
WhatConverts lead tracking plugin for Fastify — lead CRUD, account management, profile management, and call recording retrieval.
