Developer recipes

Turn a file into a public URL inside an n8n workflow

Two HTTP Request nodes turn an n8n file into a public link. This workflow keeps the binary data intact from creation to upload, then returns the link only after the upload succeeds.

On this page

What you are importing

Download the n8n workflow JSON and import it in n8n via the workflow menu's import from file option. The chain is: Manual Trigger, a node that creates a small synthetic text file as binary data, an HTTP Request that presigns, a node that restores the original binary alongside the signed metadata, an HTTP Request that PUTs the bytes, and a final step returning publicUrl.

The critical shape problem

The presign response is JSON, and your file lives in n8n's binary property data. Those are different outputs, and an HTTP Request node replacing its input would drop the binary. That is why the workflow explicitly carries the original binary forward to the PUT node after merging it with the signed uploadUrl and contentType.

PUT node configuration

Set the PUT node's Body Content Type to n8n Binary File, not the Form-Data file option, and set Input Data Field Name to data. Send the returned contentType as the Content-Type header and configure no authentication. Multipart form uploads and JSON-wrapped bodies do not match what the signed URL expects; the URL accepts only the exact raw bytes, and no bearer token is involved.

text
Method: PUT
URL: {{ $json.uploadUrl }}
Body Content Type: n8n Binary File
Input Data Field Name: data
Header: Content-Type = {{ $json.contentType }}
Authentication: None

Timeouts and error handling

Set the HTTP timeout to 60,000 ms and disable redirects on both HTTP nodes. Leave Never Error off so failed responses surface as errors, and do not enable continue-on-error, because the final link must only be produced after the PUT succeeds. n8n's built-in retry-on-fail retries every error class, so leave it off: validation and signature errors (400, 401, 403, 413) need you to diagnose the request, and only transient failures deserve a manual rerun. Limit retries to two, pause between attempts and honor Retry-After when present. Remember the signed URL expires after 900 seconds, and re-running the presign allocates a new path.

First run

Trigger the workflow manually from the editor and process one file only. Confirm the presign node returns uploadUrl, publicUrl, contentType, path, and expiresIn, confirm the PUT returns a 2xx status, and only then treat the final publicUrl output as the result to copy out. The example creates a small text file; adapt the creation node for your own small public artifacts, keeping in mind the link is public, with no delete API and no retention guarantee.

Verified behavior

This workflow was imported and executed locally with n8n 2.38.7 on Node.js 24.21.0. The uploaded sample matched the downloaded bytes and media type. A separate test preserved all 256 byte values; a deliberately mismatched Content-Type stopped at the PUT without reaching the final URL node. The n8n Cloud editor was not part of this test.

Reference

See the n8n HTTP Request documentation for node options and the Yoink API reference for the upload contract.