As a full-stack developer and Linux enthusiast, cURL has become an indispensable tool in my toolkit. Whether creating complex pipelines or interacting with APIs, cURL helps me work more efficiently.
One of my favorite cURL capabilities is posting file data to endpoints and services. Handling file uploads is extremely common – for example when submitting data imports, sending XML/JSON documents, uploading media content etc.
In this comprehensive 3200+ word guide, I‘ll share my best tips and practices for posting files with cURL gleaned from years of experience. Follow along as I lead you on a deep dive into:
- Common file formats and MIME types
- cURL options for POST requests
- Appropriate headers to set
- Reading from files with
-d
- Real-world examples and use cases
- Debugging issues with verbose mode
- Alternative methods using forms and multipart
- Scripting file uploads for APIs and webhooks
- Rate limiting and performance considerations
By the end, you‘ll thoroughly understand multiple techniques to post any file format using the venerable cURL. Let‘s get to it!
An Introduction to Content Types and File Formats
First, a quick primer on common file types for carrying data over the internet. Servers and clients use the Content-Type header to understand the format of data received. These formats are officially termed as media types or MIME types (Multipurpose Internet Mail Extensions).
Here are some typical Content-Types and file extensions used:
Content Type | File Extensions |
---|---|
text/plain | .txt |
text/csv | .csv |
application/xml | .xml |
application/json | .json |
application/pdf | |
image/jpeg | .jpg, .jpeg |
audio/mp3 | .mp3 |
video/mp4 | .mp4 |
As a developer working with diverse file formats, having familiarity with common MIME types is essential – they dictate how clients/servers handle posted content.
Now let‘s see how to actually POST these files using cURL…
A Review of cURL POST Requests
But first, a quick refresher on making basic POST requests with cURL.
The POST method allows sending data to the server to create or update resources. Here is an example POST to login a user:
POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
username=john&password=1234
To make this request with cURL, use -X POST
and the -d
flag:
curl -X POST -d "username=john&password=1234" https://example.com/login
Key points:
-X POST
specifies the POST method-d
adds the POST body data- Content-Type defaults to
application/x-www-form-urlencoded
Easy enough! Now let‘s look at posting file data…
Reading POST Data from Files
The same -d
flag allows you to post data from files too. Instead of a raw payload, give it the path to your data file:
curl -X POST -d "@data.json" https://example.com/receive
This reads the file data.json
and includes it as the POST body.
Some notes when using files with -d
:
- Prefix the file with
@
- Omit the
@
if you want the actual filename sent - Works with any file format like JSON, XML, CSV etc.
Another option is --data-binary
which is useful for POSTing binary file contents:
curl --data-binary "@image.png" https://upload.com/media
So in summary, -d @file
reads any file format to send as data, while --data-binary @file
sends raw binary file data.
Setting the Content-Type Header
When posting files, savvy developers always set the Content-Type header explicitly.
Why is this important?
The Content-Type tells the server how to interpret the sent data. Submitting JSON as plain text, or vice-versa, will usually result in errors.
Use -H
to set bespoke headers:
curl -X POST -H "Content-Type: application/json" -d "@data.json" https://example.com
Here we indicate the file is JSON format.
Some other useful Content-Types:
Content Type | Data Format |
---|---|
text/plain | Raw text |
text/csv | Comma-separated data |
application/xml | XML documents |
application/octet-stream | Binary data |
So get into the habit of explicitly setting the Content-Type when posting file data via cURL. Your future self will thank you!
Next let‘s explore some real-world examples…
POSTing JSON Data to APIs
JSON is now the lingua franca for web APIs. As such, constantly POSTing JSON data is part and parcel of a developer‘s life these days.
Let‘s say you have a REST API for creating user accounts. It accepts a JSON payload like:
{
"firstName": "John",
"lastName": "Doe",
"email": "john@doe.com",
"age": 35
}
To POST this from a user.json
file:
curl -X POST -H "Content-Type: application/json" -d "@user.json" https://api.example.com/v1/users
The API receives nicely structured JSON data and creates the user resource. Easy!
Pro Tip: Include the API version in the endpoint URL for robustness and backwards compatibility.
Posting to JSON APIs might seem simple, but this technique is immensely powerful. Think of the possibilities:
- Scripted account provisioning
- Automated data imports
- Integration workflows
- Endpoint testing
Learning this one cURL method unlocks all sorts of interesting use cases for developers.
Sending XML and Other Structured Data
While JSON dominates modern web services, good old XML remains essential in many domains.
Financial data, inventory systems, RSS feeds, and desktop/mobile client config files often use XML formatting.
Posting XML documents works similarly to JSON. Assuming data.xml
contains some XML data:
curl -X POST -H "Content-Type: application/xml" -d "@data.xml" https://example.com/receive-xml
The same approach works for submitting CSV files, JSONLines and other structured data:
# CSV data
curl -X POST -H "Content-Type: text/csv" -d "@data.csv" https://example.com/csv
# JSON Lines
curl -X POST -H "Content-Type: application/x-jsonlines" -d "@data.jsonl" https://example.com/jsonlines
The flexibility to handle diverse data types is where cURL shines.
Uploading Media Files and Binary Data
APIs are not just for structured data like JSON or XML. Modern web apps handle all sorts of binary files:
- Images
- Videos
- Audio
- PDF Documents
- Executables
- Archives and backups
- Installers
- Firmware binaries
- Disk images
cURL can handle any media upload scenario you throw at it.
For example, let‘s post a JPG image:
curl -X POST -H "Content-Type: image/jpeg" --data-binary "@cute-kitten.jpg" https://api.myapp.com/images
Uploading videos and other audio works similarly:
# Upload MP4 video
curl -X POST -H "Content-Type: video/mp4" --data-binary "@funny-cats.mp4" https://api.myapp.com/v1/videos
# Upload MP3 audio file
curl -X POST -H "Content-Type: audio/mp3" --data-binary "@podcast.mp3" https://api.myapp.com/v1/audio
Note for binary data, it‘s best practice to use --data-binary @file
instead of the regular -d @file
option.
The point is – no matter the file format – cURL has your back!
Real-World Use Cases for Posting Data
At this point, your mind may be overflowing with ideas to apply posting file data using cURL. Here are just some exciting use cases:
API Testing
Scripted testing by uploading varied sample files to endpoints. Verify server handling for load tests, security tests, fuzzing etc.
Account Provisioning
Create user accounts, set configurations, initialize data by posting setup files.
Data Import/Export
Ingest CSV exports from databases/apps. Export data dumps.
Webhooks/Event Integrations
Many integrations involve POSTing data files on triggers.
Media Ingestion Pipelines
Frontend uploads land on API servers. POSTing simulates real file uploads for testing media workflows.
Backup to Cloud Storage
cURL + Cron = Automated cloud backups!
Hopefully this sparks even more creative integrations using file-based POSTing with cURL…
Now that you‘re swimming with ideas, let‘s talk about what happens when things go wrong…
Debugging and Troubleshooting Issues
Despite cURL‘s reliability, you may encounter various issues when posting files:
- HTTP 4xx client errors
- HTTP 5xx server errors
- No response
- Timeouts
- SSL/TLS failures
Your best friend for troubleshooting cURL problems is verbose mode with the -v
flag:
curl -v -X POST -d "@data.json" https://api.example.com/users
This prints internal details about the cURL client state and headers sent/received.
Often the verbose logs indicate exactly why requests fail – common reasons include:
- Mismatched headers and data (400 errors)
- Endpoint path/route issues (404 errors)
- Server faults (500 errors)
- Network connectivity issues
Beyond -v
output, enable additional protocols for lower-level info:
curl -v --trace-ascii /tmp/file.txt [...]
This dumps debug data about TCP/IP and SSL traffic to the specified file.
With enough verbosity, you can get to the bottom of even the most stubborn cURL problems.
Alternative Methods for POSTing Files
Up to now, we focused on using the handy -d
option to post file data. But power users have a couple more techniques up their sleeves…
1. Posting File Contents from Forms
You can load file contents into a POST body by specifying the filename in place of form data:
curl -F ‘data=@file.json‘ https://api.test
Here -F
indicates a form field, but instead of form data, the @file.json
syntax uploads the contents.
You can extend this to submitting multiple files too:
curl -F ‘user=@user.json‘ -F ‘prefs=@prefs.json‘ https://api.test
The server receives a multipart form request with JSON file contents under the named fields.
2. Binary File Uploads with Multipart Requests
For binary files like images, you can post multipart requests:
curl -F "image=@kitten.jpg" https://upload.test/pics
This structures messages with file binaries and metadata which aligns to uploading from html forms.
One downside – curl sets no content type by default, so again this needs explicit headers:
curl -F "image=@kitten.jpg" -H "Content-Type: image/jpeg" https://upload.test/pics
So in summary:
-d
– Simple method to post any text or binary file contents-F
– Alternative for text file data sent via multipart form syntax-F
+@file
– Uploads binary file in multipart syntax
Mix and match techniques to find the right approach for your particular API or service!
Script All the Things! Optimizing cURL Commands
While cURL commands are handy to run one-off uploads, typically we want to incorporate them into reusable scripts.
Here are some best practices for safely scripting cURL file uploads:
Increase Timeouts
Have cURL wait longer for responses before timing out:
curl --connect-timeout 60 --max-time 120 https://example.com
Useful for long requests or occasionally slow networks.
Fail Safely with Error Codes
Catch errors from cURL in your scripts:
if ! curl "...file..."; then
echo "Upload failed" >&2
exit 1
fi
This helps scripts fail gracefully.
Shield Secrets from Code/Logs
Hide passwords/API keys using dedicated config files:
# .secrets
API_KEY=738gjTGYT$dyt84539
source .secrets
curl -u $API_KEY https://api.test
Adding config helps manage secrets during development.
Enable Retries to Handle Flakes
Retry uploads before raising errors:
RETRIES=0
MAX=5
until [ $RETRIES -ge $MAX ]; do
curl -f https://test.com/data.json
RETRIES=$[$RETRIES+1]
done
# Failed after 5 retries
echo "Upload error"
This begets resilience for finicky endpoints.
Throttling requests also helps limit impact on the destination server…
Playing Nice – Throttling and Rate Limiting
A final tip – resist overwhelming endpoints with curl script barrage.
APIs and services often implement rate limiting – only allowing x requests per minute/hour to prevent runaway resource usage.
When possible, respect rate limits using simple throttling:
# API allows 60 req/hour
REQ_LIMIT=60 # requests per hour
REQ_INTERVAL=3600 # rate limit window (seconds)
REQ_FREQUENCY=$(($REQ_INTERVAL / $REQ_LIMIT)) # seconds between requests
for ((i=0; i < $REQ_LIMIT; i++))
do
# Upload file...
curl -X POST -d "@data-$i.json" https://api.example.com
# Throttle requests
sleep $REQ_FREQUENCY
done
This crude throttler spaces out uploads at the allowed rate. For APIs lacking published rate limits, monitor response headers and error codes to infer sustainable frequencies.
Ideally APIs would communicate limits directly – but lacking that, nonce counts, correlating identifiers and timestamps often indicate request velocity.
Bottom line – be a conscientious curl consumer when scripting! Don‘t bash endpoints without some semblance of throttling.
In Closing
That wraps up this epic guide on posting files with cURL. To recap key discussion points:
- Common file types and content encodings
- Multipart form uploads
- Setting headers appropriately
- Reading file contents with
-d
- Use cases like testing, integrations and data imports
- Scripting best practices
- Debugging issues in verbose mode
- Rate limiting for playing nice
These skills to effortlessly post data from files demonstrate cURL mastery. I‘m excited for all the automation, integrations and pipeline building in your future!
If any questions pop up, feel free to reach out! I welcome feedback to improve these writings. Until next time, may your uploads never fail.
Happy curling!