PHP File Upload

Upload Files From PHP With curl or Guzzle

Upload files from PHP with curl. No SDK, REST API, CDN delivery, prepaid credits.

The aws-sdk-php package is a heavyweight Composer dependency for what is, at heart, a few HTTP requests — and on shared hosting or a lean WordPress install you may not want it at all. files.link works with the curl extension that ships with PHP, or with Guzzle if you already have it, and the upload is three calls. Request a presigned URL by POSTing metadata to /v1/files/{folderId} with your API key in the Authorization header (raw key, no Bearer prefix); PUT the bytes to the returned url; POST /v1/files/confirm-upload with the file id. With the bundled curl extension and no Composer dependency at all:

php
<?php
$api = 'https://api.files.link';
$key = getenv('FILESLINK_KEY');
$folder = 'your-folder-id';
$path = 'invoice.pdf';

// 1. request a presigned PUT URL
$ch = curl_init("$api/v1/files/$folder");
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => ["Authorization: $key", 'Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode(['filesMetadata' => [['name' => 'invoice.pdf']]]),
]);
$meta = json_decode(curl_exec($ch), true);
$slot = $meta['urls'][0];

// 2. PUT the file bytes
$ch = curl_init($slot['url']);
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_PUT => true,
  CURLOPT_INFILE => fopen($path, 'rb'),
  CURLOPT_INFILESIZE => filesize($path),
]);
curl_exec($ch);

// 3. confirm
$ch = curl_init("$api/v1/files/confirm-upload");
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => ["Authorization: $key", 'Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode(['ids' => [$slot['id']]]),
]);
curl_exec($ch);

Using CURLOPT_INFILE streams the file rather than loading it into a string, which keeps you under PHP's memory_limit for large uploads — the usual bottleneck in PHP file handling. In a framework you'd reach for the native client: Laravel's Http::withHeaders(['Authorization' => $key])->post(...) for the metadata and confirm steps and ->withBody(...)->put(...) for the bytes; Symfony's HttpClient or Guzzle work the same way.

On WordPress, wp_remote_post and wp_remote_request (which supports PUT) let a plugin fire the upload from a hook with the key stored in wp_options — handy for offloading media to a CDN-backed store without bundling an SDK. Confirmed public files come back as permanent CDN URLs; private files use signed URLs with a short expiry, chosen at upload with a flag. For files above ~100MB (up to 1TB) the multipart endpoint streams chunks so you never exceed memory_limit.

Billing is prepaid credits, so an over-eager batch job costs credits, not a runaway bill. Compared to aws-sdk-php you drop a large dependency and a credentials file for a contract that's a few curl_setopt lines. Related: the WordPress media storage page for that specific offload, and the cloud file storage API page for the full route reference.

Benefits With No Complexity

Global CDN delivery

Your files are served from 450+ edge locations worldwide.

Edge-cached worldwide

Files are cached close to your users for fast delivery.

Signed-URL security

Private files stay protected with time-limited access.

What You Get

Unlimited files

Upload as many files as you need.

Unlimited storage

There is no storage limit.

Public + Private storage

Private files are fully secured.

CDN ready links

Upload directly to 450+ edge locations worldwide.

Prepaid credits

No subscription. Pay only for the storage and bandwidth you use.

More coming soon

We have plenty of features coming!

How files.link Works

1. Upload

Create a project and upload your first file.

2. Copy

Copy the CDN link.

3. Use Anywhere

Paste and enjoy the blazing speed.

Why Developers Choose files.link

A Better Way to Store & Deliver Files

AWS S3 (aws-sdk-php)Cloudinary SDKGoogle Cloud Storagefiles.link
Works with bundled curl (no Composer install)
Smaller dependency footprint
Streams via CURLOPT_INFILE (low memory)
Laravel / Symfony / WordPress friendly
Global CDN delivery included
Multipart up to 1TB per file
Prepaid credits, no surprise bills

Calculate Your Needs

Storage

0GB

Egress

0GB

CDN Bandwidth

0GB
Total: $0.000/month

Upload Files from PHP

  • Global CDN delivery
  • Edge-cached worldwide
  • Signed-URL security
  • Unlimited files
  • Unlimited storage
  • Public + Private storage
  • No subscription — prepaid credits keep spend predictable
Start Uploading from PHP

Frequently Asked Questions

What does a PHP upload look like?
Three calls. (1) POST metadata JSON to /v1/files/{folderId} with the Authorization header → decode the presigned url and id from the response. (2) curl PUT the bytes to that url (CURLOPT_PUT with CURLOPT_INFILE to stream). (3) POST /v1/files/confirm-upload with { 'ids': [id] }. No aws-sdk-php, no credentials file.
How do I do this in Laravel?
Use the native HTTP client: Http::withHeaders(['Authorization' => $key])->post(...) for the metadata and confirm steps, and ->withBody(file_get_contents($path), $mime)->put($url) for the bytes. No extra package required.
Does it work with WordPress plugins?
Yes. wp_remote_post handles the metadata and confirm POSTs, and wp_remote_request supports the PUT for the bytes. Store the API key in wp_options and fire the upload from your plugin's hook — useful for offloading media to CDN-backed storage.
How do I avoid hitting memory_limit on large files?
Stream rather than buffer: with curl use CURLOPT_INFILE so the file isn't loaded into a PHP string. For files over ~100MB, use the multipart endpoint (up to 1TB) and PUT chunks, which keeps memory flat regardless of file size.
How are uploaded files served?
Public files return a permanent CDN URL; private files use signed URLs with a short default expiry. You choose public or private at upload time with a flag — there's no separate subsystem to configure.
General Questions
Is there a subscription?
No. files.link uses prepaid credits, so storage, bandwidth, and API usage are deducted from your balance as you go. The app explains the payment step before uploads are enabled — no monthly subscription and no per-user fees.
What is files.link?
files.link is a developer-first file platform that makes it simple to store, secure, and deliver files globally. It provides signed URLs, public/private access, and an API-first design so you can integrate file delivery into any app without the usual complexity.
How does billing work?
files.link uses prepaid credits. As you use storage, bandwidth, and API requests, credits are deducted daily. When your balance runs low, we automatically recharge it using your saved card. If an auto-recharge doesn't go through, your files and links stay put — you simply update your payment method or top up manually to keep going. No monthly subscriptions — just simple usage-based pricing.
How secure is my data?
All files are encrypted at rest and in transit. You can use signed URLs for private files, control access with permissions, and rely on enterprise-grade infrastructure for data protection.

Related

files.link
Copyright © 2026
All rights reserved
ContactGuidesGlossaryStatusLegal