How to upload file to Flask API endpoint with curl

Below code explains how to upload a file with curl to your flask API.

Official flask documentation is providing lots of options how to enhance uploading functionality/security of your API (https://flask.palletsprojects.com/en/2.0.x/patterns/fileuploads/), also explains the need for using secure_filename method from werkzeug.

Flask app:

import os
from flask import Flask
from flask import request
from werkzeug.utils import secure_filename

app = Flask(__name__)

# we will want to download files under current app dir
app_dir = os.path.dirname(os.path.realpath(__file__))
print('app_dir', app_dir)

@app.route('/uploads', methods=['POST', 'PUT'])
def upload_file():
    target = os.path.join(app_dir, 'uploads/files/')
    if not os.path.isdir(target):
        os.makedirs(target)

    if request.method  == 'PUT': # alternatively use 'POST'
        # the 'file' key corresponds to 'file' marker in curl call
        # curl -i -X PUT -H "Content-Type: multipart/form-data" 
        #       -F "file=@/home/coil/Desktop/uploads/my_upload.txt" 
        #       http://localhost:5000/uploads

        f = request.files['file']
        file_name = secure_filename(f.filename)
        destination = '/'.join([target, file_name])
        f.save(destination)

        return 'file uploaded successfully'

if __name__ == '__main__':
    app.run(port=5000, debug=True)

Send file with curl call (specify file with full path):

coil@coil-VM:~/Desktop/uploads$ curl -i -X PUT -H "Content-Type: multipart/form-data" -F "file=@/home/coil/Desktop/uploads/my_upload.txt" http://localhost:5000/uploads
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 26
Server: Werkzeug/2.0.2 Python/3.9.7
Date: Mon, 07 Feb 2022 22:45:59 GMT

file uploaded successfully
coil@coil-VM:~/Desktop/uploads$ 

File will be uploaded to in relative path to directory from which the flask script runs:

└── uploads
    └── files
        └── my_upload.txt

Sources: