X Enterprises
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

NameTypeRequiredDescription
fileBuffer | StreamYesFile content.
filenamestringYesOriginal filename — used for extension and MIME type detection.
options.folderstringNoPrefix folder (e.g., "avatars"). Prepended to the generated key.
options.keystringNoExplicit storage key. Overrides auto-generation entirely.
options.contentTypestringNoMIME type override. Auto-detected from extension if omitted.
options.metadataobjectNoCustom S3 metadata key-value pairs.
options.useRandomNamebooleanNoAppend random hex suffix to avoid collisions. Default true.
options.aclstringNoPer-file ACL. Falls back to plugin-level acl.

uploadMultiple

NameTypeRequiredDescription
filesarrayYesNon-empty array of { file, filename, acl? } objects.
optionsobjectNoShared options applied to all files (same shape as upload options).

Returns

FieldTypeDescription
keystringThe storage key of the uploaded file.
urlstringFull public URL (publicUrl + "/" + key).
sizenumber | nullFile size in bytes; null for stream inputs.
contentTypestringMIME type used for the upload.
bucketstringName of the S3 bucket.

Throws

  • [xStorage] file is required for upload — if file is falsy.
  • [xStorage] filename is required and must be a string — if filename is missing.
  • [xStorage] files must be a non-empty array — if files is 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

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 }
Copyright © 2026