Rails File Upload
Upload Files from Rails Controllers Without Active Storage
Upload files from Rails controllers with net/http. No SDK, REST API, CDN delivery.
Active Storage with an S3 service is the default Rails answer, but it is a lot of machinery — a service config, two extra tables, blob/attachment records, and a direct-upload JS controller — when all you want is to send a file somewhere and get back a CDN URL. files.link is three HTTP calls from a controller, no Active Storage, no aws-sdk-s3 gem, no storage.yml.
And because it is just HTTP, the same code runs from a Sidekiq job, a rake task, or a one-off script — places where Active Storage's record dependencies get awkward.
The browser posts multipart/form-data; Rails hands you an ActionDispatch::Http::UploadedFile via params[:upload]. You read its bytes and PUT them to the presigned URL.
require 'net/http'
class UploadsController < ApplicationController
KEY = Rails.application.credentials.fileslink_key
BASE = 'https://api.files.link'
def create
file = params[:upload]
bytes = file.read
meta = { filesMetadata: [{ name: file.original_filename, size: bytes.bytesize, type: file.content_type }] }
r1 = Net::HTTP.post(URI("#{BASE}/v1/files/#{ENV['FILESLINK_FOLDER']}"),
meta.to_json, 'Authorization' => KEY, 'Content-Type' => 'application/json')
slot = JSON.parse(r1.body)['urls'].first
put = Net::HTTP.new(URI(slot['url']).host, 443); put.use_ssl = true
put.send_request('PUT', URI(slot['url']).request_uri, bytes, 'Content-Type' => file.content_type)
Net::HTTP.post(URI("#{BASE}/v1/files/confirm-upload"),
{ ids: [slot['id']] }.to_json, 'Authorization' => KEY, 'Content-Type' => 'application/json')
render json: { id: slot['id'] }
end
endPrefer HTTParty or Faraday? Swap the three net/http calls for their equivalents; the endpoints and bodies are unchanged. The Authorization header carries the raw API key — no Bearer prefix — and the cleanest place for that key is Rails encrypted credentials (Rails.application.credentials.fileslink_key), never a hardcoded string. For anything but tiny files, push the three-call flow into an ActiveJob/Sidekiq job so the controller responds instantly and the upload finishes in the background; pass a Tempfile path rather than raw bytes to keep the job payload small. files.link and Active Storage do not collide — you can keep Active Storage for some attachments and use files.link for CDN-served public assets.
Files come back as CDN URLs with per-file visibility, encrypted at rest, billed from prepaid credits.
Benefits With No Complexity
Global CDN delivery
Edge-cached worldwide
Signed-URL security
What You Get
Unlimited files
Unlimited storage
Public + Private storage
CDN ready links
Prepaid credits
More coming soon
How files.link Works
1. Upload
2. Copy
3. Use Anywhere
Why Developers Choose files.link
A Better Way to Store & Deliver Files
| Active Storage + S3 | Cloudinary (cloudinary gem) | files.link | |
|---|---|---|---|
| No Active Storage config or extra tables | |||
| Works in jobs, rake tasks, scripts | |||
| Global CDN delivery on every file | |||
| No aws-sdk-s3 gem / IAM setup | |||
| Prepaid credits (no surprise bills) |
Calculate Your Needs
Storage
Egress
CDN Bandwidth
Wire Up Rails File Uploads
- Global CDN delivery
- Edge-cached worldwide
- Signed-URL security
- Unlimited files
- Unlimited storage
- Public + Private storage
- No subscription — prepaid credits keep spend predictable