cURL by Example: Upload File via PUT
Upload a file using the PUT method. Common in WebDAV and RESTful storage APIs.
Code
# Upload local file to remote server
curl -T local.txt https://example.com/upload/remote.txt
# Upload multiple files (globbing)
curl -T "img[1-10].png" https://example.com/upload/
# Upload to FTP server
curl -T backup.zip ftp://ftp.example.com/backups/ --user user:passExplanation
The -T flag (or --upload-file) is cURL's mechanism for uploading files using the HTTP PUT method, sending the file content as the raw request body without any encoding or wrapping. This is fundamentally different from form-based uploads using -F: PUT sends the file content directly as the entire HTTP request body, while -F wraps the file in a multipart/form-data envelope with boundaries and headers. PUT is the HTTP method designed for storing or updating resources at a specified URI, making it the natural choice for RESTful APIs, WebDAV servers, object storage systems like AWS S3, and file hosting services that accept direct binary uploads.
How -T Works: The syntax is straightforward: curl -T localfile.txt https://example.com/path/remotefile.txt. cURL reads the local file and streams its contents to the server using HTTP PUT method (for HTTP/HTTPS) or STOR command (for FTP). For HTTP, the file content becomes the request body exactly as-is with no transformation, and cURL automatically sets Content-Length header to the file size. Unlike POST with multipart data, there are no field names, boundaries, or Content-Disposition headers—it's just raw file data. This makes PUT ideal for APIs like PUT /api/files/document.pdf where the server treats the entire request body as the new file content. Many RESTful storage APIs (MinIO, S3-compatible services, WebDAV) specifically require PUT for uploads because it maps cleanly to the REST concept of "put this resource at this URL".
Advanced PUT Features: The -T flag supports several powerful features. Multiple file uploads: -T "file{1,2,3}.txt" or -T "img[1-10].png" uses shell globbing to upload multiple files in sequence. Upload from stdin: cat dynamic.data | curl -T - https://example.com/upload where - tells cURL to read from standard input, enabling piped uploads from other commands. FTP uploads: curl -T backup.zip ftp://ftp.example.com/backups/backup.zip --user username:password uploads via FTP protocol. Custom content type: While -T doesn't set Content-Type automatically, you can add it manually: curl -T photo.jpg -H "Content-Type: image/jpeg" https://api.example.com/upload. Resume partial uploads: Combine with -C - to resume interrupted uploads: curl -C - -T largefile.zip ftp://server.com/.
PUT vs POST with -F: Understanding when to use -T (PUT) versus -F (POST multipart) is crucial. Use -T when: the API documentation specifies PUT method, you're uploading a single file that should replace/create a resource at the target URL, the server expects raw file content as the request body (common in object storage, WebDAV, RESTful file APIs), or you're working with FTP. Use -F when: uploading through HTML forms, sending multiple files or mixing files with text fields in one request, the API expects multipart/form-data format (common in traditional web applications), or you need field names for each uploaded file. Example API comparison: S3-style APIs use -T: curl -T file.jpg -H "x-amz-acl: public-read" https://bucket.s3.amazonaws.com/file.jpg, while a typical web form uses -F: curl -F "[email protected]" -F "caption=My Photo" https://example.com/upload.
Code Breakdown
-T local.txt reads the file and streams it to the server.
