Image Uploads with Google Cloud Storage and Flask

The ability to upload files, especially images, to a server is an essential feature for many web applications. From profile photos to document storage, providing users with the ability to upload files can significantly enhance the user experience. This article will walk you through the process of adding a file upload functionality to a Python backend exposed via a Flask API.

Overview

The code snippet provided showcases a Flask route (/upload-image) that allows for image uploads. Once an image is uploaded, it's temporarily saved to the server's file system. Following this, it's uploaded to Google Cloud Storage (GCS) and made publicly accessible. The public URL of the uploaded image is then returned as the API response.

API Code


@app.route('/upload-image', methods=['POST'])
def upload_image():
    file = request.files.get('image')
    if not file:
        return jsonify({'error': 'Image is required'}), 400,
    tmp_file = f'/tmp/{file.filename}'
    file.save(tmp_file)
    url = gcs_upload_image(tmp_file)
    os.remove(tmp_file)
    return jsonify({'url': url})

Let's break down the process step-by-step:

1. Flask Route for File Upload

The route /upload-image is defined to accept POST requests:


@app.route('/upload-image', methods=['POST'])
def upload_image():
    ...

This function starts by checking if there's a file attached with the key 'image'. If not, an error is returned

file = request.files.get('image')
if not file:
    return jsonify({'error': 'Image is required'}), 400,

2. Saving the Image Temporarily

After validating the presence of the uploaded file, it's temporarily saved to the server's /tmp directory:

tmp_file = f'/tmp/{file.filename}'
file.save(tmp_file)

The use of the /tmp directory ensures that the file is not stored permanently on the server, as it's meant to be a short-lived location.

Uploading the Image to Google Cloud Storage

With the image saved temporarily, the next step is to upload it to GCS:

url = gcs_upload_image(tmp_file)

The upload_image function is responsible for interfacing with GCS:

def gcs_upload_image(filename: str):
    storage_client: storage.Client = storage.Client()
    bucket: storage.Bucket = storage_client.bucket(GCS_ASSETS_BUCKET)
    blob: storage.Blob = bucket.blob(filename.split("/")[-1])
    blob.upload_from_filename(filename)
    blob.make_public()
    public_url: str = blob.public_url
    print(f"Image uploaded to {public_url}")
    os.remove(filename)
    return public_url

Here's a breakdown of the function:

  • A connection is established with GCS using the storage.Client().
  • The desired bucket (specified by GCS_ASSETS_BUCKET) is accessed.
  • A new blob (GCS's term for an object) is created with the filename.
  • The image is uploaded using upload_from_filename.
  • The blob is made public so anyone can access the image via its URL.
  • The temporary file is deleted from the server using os.remove.
  • The public URL of the blob is returned.

Returning the Public URL

Finally, the public URL of the uploaded image is returned as the API response:pythonCopy codereturn jsonify({'url': url})

Considerations

While the provided code offers a clear and straightforward way to upload files to GCS, there are a few important considerations:

  1. Security: It's essential to validate and sanitize uploaded files to prevent potential security threats. This can include checking the file's MIME type or using libraries to ensure the file is a genuine image.
  2. File Naming: To prevent files from overwriting each other, consider generating unique filenames before uploading them to GCS.
  3. Error Handling: Always account for potential errors during the file upload process, such as network failures, GCS outages, or quota restrictions.
  4. Cleaning Temporary Files: Ensure that temporary files are deleted even if the upload to GCS fails. This prevents the server's storage from filling up unnecessarily.

Conclusion

Incorporating file upload functionality into a Flask API allows for a richer user experience and paves the way for various features in web applications. While the process of uploading images to GCS is relatively straightforward, always prioritize security and error handling to ensure a smooth and safe user experience.