space.fs.write()

Store a file in a bucket from a string, bytes, a Blob, or a stream, and get the stored file back.

Stores a file at a path, replacing any file already there. Use it for anything your server makes or receives, such as an invoice PDF or a photo a customer sent.

space.fs.write(
  path: string | { bucket: string; key: string },
  data: string | Uint8Array | ArrayBuffer | Blob | ReadableStream<Uint8Array>,
  options?: {
    contentType?: string
    verify?: boolean
    signal?: AbortSignal
    timeoutMs?: number
  }
): Promise<StoredFile>

The call starts an upload, sends the file’s bytes, and finishes the upload. If a step after the start fails, it cancels the upload before the promise rejects.

Parameters

pathstring | { bucket, key }Required

Where to store the file: bucket/key as one string, such as invoices/2026/0001.pdf, or an object such as { bucket: "invoices", key: "2026/0001.pdf" }.

  • The bucket is 3 to 63 lowercase letters, digits, and single hyphens, starting and ending with a letter or digit.
  • The key is 1 to 1,024 bytes. It cannot start or end with /, hold //, have a folder named . or .., or hold control characters.
datastring | Uint8Array | ArrayBuffer | Blob | ReadableStreamRequired

The file’s contents, at most 100,000,000 bytes. A string is stored as UTF-8. A stream is read to its end before the upload starts, so the whole file is held in memory. The package exports the limit as maxFileBytes.

options.contentTypestring

The file’s media type, such as image/png, with optional parameters such as ; charset=utf-8. When you leave it out, it comes from the Blob’s own type, then from the key’s extension. Without either, a string is stored as text/plain; charset=utf-8 and anything else as application/octet-stream.

options.verifyboolean

true by default: the file’s SHA-256 digest is sent with the upload, and storage refuses any other bytes. false sends no digest, and the stored file then has no sha256.

options.signalAbortSignal

Cancels the call when it aborts. The promise then rejects with aborted, and the upload is cancelled.

options.timeoutMsnumber

The longest each request may take, in milliseconds. The client’s timeoutMs when you leave it out, 30,000 by default.

The extensions write knows are avif, csv, gif, html, jpeg, jpg, js, json, md, mp3, mp4, pdf, png, svg, txt, wav, webm, webp, xml, and zip. For any other, pass contentType.

Returns

A promise for the stored File.

Errors

The promise rejects with a SpaceError. The call never throws before it returns the promise, and when an argument is wrong, nothing is sent.

CodeWhen
validation_failedThe path, the data, or an option is wrong. issues names each field, such as path.key
file_too_largeThe file is over 100,000,000 bytes. Nothing is sent
not_foundThe bucket does not exist
storage_quota_reachedThe file does not fit in the project’s storage
upload_limit_reachedThe project has too many uploads in progress
upload_failedStorage refused the file’s bytes
upload_size_mismatchThe bytes that arrived do not match the size or digest
forbiddenThe API key may not upload files

Every call can also fail with the codes listed on SpaceError, such as timeout and network_error.

Example

save-invoice.ts
import { readFile } from "node:fs/promises"

import { space } from "digitospace"

const pdf = await readFile("invoice-0001.pdf")
const file = await space.fs.write("invoices/2026/dar-es-salaam/0001.pdf", pdf)

console.log(file.key, file.size, file.contentType)

Pass contentType when the key’s extension does not say enough, such as a CSV report with its character set:

save-report.ts
import { space } from "digitospace"

const rows = [
  ["branch", "sales_tzs"],
  ["Kariakoo", "4500000"],
  ["Mlimani City", "3250000"],
]
const csv = rows.map((row) => row.join(",")).join("\n")

await space.fs.write("reports/2026/09/sales.csv", csv, {
  contentType: "text/csv; charset=utf-8",
})

For how uploads work in the service, see Upload files.

Last updated