Reference · Tools

Upload to Spaces

Uploads a local file to DigitalOcean Spaces

Action (binary) Data & Storage v1 Binary data

Upload to Spaces sends a file — from disk or from a binary property on the item — to DigitalOcean Spaces and returns the object URL, key and metadata. A typical build is persisting a generated report or image and passing its URL to the message that announces it.

Node type
Action (binary)
Parameters
15
Outputs
Output, Error
Credentials
DigitalOcean Spaces

Upload to Spaces

Upload to cloud storage

Overview

Uploads a local file (e.g., produced by Write to File) or a binary property to DigitalOcean Spaces and stores the object URL + key on the item. Objects are uploaded with a private ACL by default; set ACL to public-read when the returned URL must be fetchable without credentials. Supports expressions like {{ $json.fileWrite.fullPath }}.

Category: Data & Storage
Tool Name: upload_to_spaces
Version: 1

Appearance: Icon: uploadCloud | Color: #0ea5e9

Node Type

Action (Binary) — handles file/binary data operations

Input / Output

DirectionPort(s)
InputInput
OutputOutput, Error

Credentials

This tool requires DigitalOcean Spaces credentials. See the Credentials Guide for setup instructions.

Parameters

ParameterTypeRequiredDefaultDescription
Spaces EndpointstringYeshttps://nyc3.digitaloceanspaces.comSpaces endpoint URL (region-specific). Example: https://nyc3.digitaloceanspaces.com
Spaces RegionstringYesnyc3Spaces region (e.g., nyc3, sfo3, ams3).
Spaces BucketstringYesBucket name to upload into.
CDN Base URL (Optional)stringNoIf provided, returned URLs will be built from this base URL instead of https://{bucket}.{region}.digitaloceanspaces.com
File PathstringYes{{ $json.fileWrite.fullPath }}Absolute path to the local file to upload. Typically from write_to_file: {{ $json.fileWrite.fullPath }}.
Key PrefixstringNouploadsPrefix/folder within the bucket (e.g., uploads, outputs, logs).
Key TemplatestringYes{{ $json.fileWrite.relativePath }}Object key path (relative) inside the bucket. Supports expressions. Example: {{ $json.fileWrite.relativePath }}
ACLoptionsNoprivateObject ACL. Defaults to “private” for safety; set to “public-read” to allow direct URL fetches.
Options: private, public-read
Content Type ModeoptionsNoautoHow to set Content-Type on the upload.
Options: auto (detected from the file), override
Content Type OverridestringNoUsed only when Content Type Mode = “Override”. Example: text/markdown (shown when Content Type Mode is override)
Delete Local File After UploadbooleanNofalseIf true, deletes the local file after a successful upload (useful for ephemeral job/pod storage).
Include Input FieldsbooleanNotrueIf true, copies the input item JSON into the output item JSON.
Result Field NamestringNospacesUploadWhere to place upload result metadata on the output JSON.
Binary PropertystringNoIf set, uploads from this binary property instead of file path. Names are case-sensitive — see the upstream node’s Binary Data panel for the exact names to use. File Path is still resolved and sandbox-checked first, so leave it at a valid in-sandbox value.
Max ConcurrencynumberNo25Maximum number of items to upload concurrently. Range 1–100.

Output Data

One output item per input item. The upload result is written to the property named by Result Field Name (spacesUpload by default); the rest of the item JSON passes through when Include Input Fields is on, and binary data is forwarded.

{
  "spacesUpload": {
    "ok": true,
    "bucket": "my-bucket",
    "key": "uploads/2026/report.pdf",
    "url": "https://my-bucket.nyc3.digitaloceanspaces.com/uploads/2026/report.pdf",
    "mimeType": "application/pdf",
    "sourceFilePath": "…/report.pdf",
    "sizeBytes": 84213,
    "acl": "private",
    "uploadedAt": 1765432100000
  }
}
FieldMeaning
oktrue on a successful upload
bucketThe bucket the object was written to
keyThe final object key — Key Prefix joined to the resolved Key Template
urlURL of the object, built from CDN Base URL when you set one, otherwise from bucket + region. Built from the key, not from the ACL — with the default private ACL this link exists but anonymous fetches of it are refused
mimeTypeThe Content-Type stored with the object
sourceFilePathThe file that was actually sent
sizeBytesSize of that file, or null when it could no longer be measured (for example after Delete Local File After Upload removed it)
aclThe ACL applied to the object
uploadedAtUpload time, in epoch milliseconds

Set Binary Property to upload a file produced by an upstream node instead of one on disk: when the named property is present on the item its contents are uploaded, and otherwise the node falls back to reading File Path.

Reference the result downstream by expression, e.g. {{ $json.spacesUpload.url }}.

Usage Examples

  • upload the file to cloud storage
  • save the image to Spaces
  • push the report to S3
  • store the backup in the cloud
  • upload results to the bucket

Example Configuration

Basic upload configuration:

{
  "id": "upload_to_spaces",
  "name": "Upload to DigitalOcean Spaces",
  "type": "upload_to_spaces",
  "parameters": {
    "endpoint": "https://nyc3.digitaloceanspaces.com",
    "region": "nyc3",
    "bucket": "my-bucket",
    "filePath": "{{ $json.fileWrite.fullPath }}",
    "keyPrefix": "uploads",
    "keyTemplate": "{{ $json.fileWrite.relativePath }}",
    "acl": "public-read",
    "contentTypeMode": "auto"
  }
}

Upload with content type override:

{
  "id": "upload_to_spaces",
  "name": "Upload PDF with Custom Content Type",
  "type": "upload_to_spaces",
  "parameters": {
    "endpoint": "https://sfo3.digitaloceanspaces.com",
    "region": "sfo3",
    "bucket": "documents-bucket",
    "filePath": "{{ $json.fileWrite.fullPath }}",
    "keyPrefix": "pdfs",
    "keyTemplate": "{{ $json.fileWrite.relativePath }}",
    "acl": "public-read",
    "contentTypeMode": "override",
    "contentTypeOverride": "application/pdf"
  }
}

Upload with CDN and cleanup:

{
  "id": "upload_to_spaces",
  "name": "Upload with CDN and Local Cleanup",
  "type": "upload_to_spaces",
  "parameters": {
    "endpoint": "https://ams3.digitaloceanspaces.com",
    "region": "ams3",
    "bucket": "static-assets",
    "cdnUrl": "https://cdn.example.com",
    "filePath": "{{ $json.fileWrite.fullPath }}",
    "keyPrefix": "images",
    "keyTemplate": "{{ $now.format('YYYY/MM/DD') }}/{{ $json.fileWrite.filename }}",
    "acl": "public-read",
    "contentTypeMode": "auto",
    "deleteLocalAfterUpload": true,
    "resultFieldName": "uploadResult"
  }
}

Private upload configuration — private is the default, so ACL is spelled out here only for clarity:

{
  "id": "upload_to_spaces",
  "name": "Private File Upload",
  "type": "upload_to_spaces",
  "parameters": {
    "endpoint": "https://nyc3.digitaloceanspaces.com",
    "region": "nyc3",
    "bucket": "private-documents",
    "filePath": "{{ $json.fileWrite.fullPath }}",
    "keyPrefix": "confidential",
    "keyTemplate": "{{ $json.fileWrite.relativePath }}",
    "acl": "private",
    "contentTypeMode": "auto",
    "includeInput": false,
    "maxConcurrency": 5
  }
}

After Write to File — a typical workflow where a file is generated and then uploaded:

{
  "nodes": [
    {
      "id": "write_file",
      "name": "Generate Report",
      "type": "write_to_file",
      "parameters": {
        "fileName": "report.pdf",
        "content": "{{ $json.report_data }}"
      }
    },
    {
      "id": "upload_file",
      "name": "Upload to Spaces",
      "type": "upload_to_spaces",
      "parameters": {
        "bucket": "reports-bucket",
        "filePath": "{{ $json.fileWrite.fullPath }}",
        "keyTemplate": "{{ $json.fileWrite.relativePath }}",
        "deleteLocalAfterUpload": true
      }
    }
  ]
}

Organized storage with date prefixes:

{
  "id": "upload_to_spaces",
  "name": "Organized Upload",
  "type": "upload_to_spaces",
  "parameters": {
    "bucket": "my-storage",
    "filePath": "{{ $json.fileWrite.fullPath }}",
    "keyPrefix": "{{ $now.format('YYYY/MM') }}",
    "keyTemplate": "{{ $workflow.id }}/{{ $json.fileWrite.filename }}",
    "contentTypeMode": "override",
    "contentTypeOverride": "text/markdown"
  }
}

High-volume upload with concurrency control:

{
  "id": "upload_to_spaces",
  "name": "Batch Upload",
  "type": "upload_to_spaces",
  "parameters": {
    "bucket": "batch-processing",
    "filePath": "{{ $json.fileWrite.fullPath }}",
    "keyTemplate": "batch-{{ $now.unix() }}/{{ $json.fileWrite.filename }}",
    "maxConcurrency": 20,
    "deleteLocalAfterUpload": true,
    "resultFieldName": "batchUpload"
  }
}

Upload from a binary property — uploads the bytes held on the item’s data property rather than a file on disk. Key Template supplies the object name because there is no fileWrite result to borrow one from:

{
  "id": "upload_to_spaces",
  "name": "Upload Binary Attachment",
  "type": "upload_to_spaces",
  "parameters": {
    "endpoint": "https://nyc3.digitaloceanspaces.com",
    "region": "nyc3",
    "bucket": "my-bucket",
    "binaryProperty": "data",
    "keyPrefix": "attachments",
    "keyTemplate": "{{ $json.fileName }}",
    "acl": "public-read",
    "contentTypeMode": "auto"
  }
}

Error Handling

ModeBehavior
stopHalts workflow on first error
continueSkips failed items, passes successful ones through
errorPortRoutes failed items to Error output port

Tips

Uploads a file from disk, or the bytes on a binary property, to DigitalOcean Spaces (S3-compatible storage) and returns the object URL. Use when you need to persist generated files, images, or data exports to cloud storage. Produces items containing the upload URL, object key, and file metadata. Uploads are private by default — switch the ACL to public-read when the URL has to be fetchable without credentials.

Key Rules and Gotchas

  1. ACL defaults to private. The examples above that omit acl (After Write to File, Organized Storage, Batch Upload) upload private objects. The returned url is always built from the key, so it will look like a working link and return an access-denied error to anonymous fetchers. Set "acl": "public-read" whenever the URL is meant to be handed to a browser, an email, or a downstream node that fetches it without credentials.

  2. Max Concurrency defaults to 25 (range 1–100), and the node’s own global cap is 50 concurrent uploads across the whole engine.

  3. File Path is validated even when Binary Property is set. It must resolve to a non-empty path under /app/workflow-tmp/, /app/agent_files/ or /app/outputs/; anything else fails the item before the upload starts. Its default expression satisfies this, so leave it alone rather than blanking it out for binary uploads.

  4. Delete Local File After Upload only deletes inside the sandbox. A source outside the allow-list is logged as a warning and left in place — the upload itself still succeeds.

Frequently asked questions

Why is my uploaded file not publicly accessible?

Uploads are private by default. Switch the ACL to public-read when the URL has to be fetchable without credentials — otherwise the returned URL will not work for anonymous visitors.

Where can the file come from?

Either a file on disk or the bytes on a binary property of the incoming item, so it chains after generation, download or conversion steps.

What comes back?

The upload URL, the object key and file metadata, so downstream nodes can both link to and later address the object.

Which credential does it need?

A DigitalOcean Spaces credential.

Build with the Upload to Spaces node

Drop it into a workflow, wire it to an agent, or call it on a schedule. You'll need DigitalOcean Spaces credentials first.

Open BusyBot

Last updated . Spotted something wrong? Tell us.