Implementing Image and File Uploads via Python APIs
Uploading binary assets such as images requires sending the data as a file stream. When using the Python requests library, the files parameter handles the construction of multipart/form-data automatically. The dictionary keys correspond to the form field names expected by the API, while the values specify the file metadata and content.
import requests
import os
def transmit_image_resource(directory, filename, mime_type='image/jpeg'):
api_endpoint = 'https://api.service.example/upload'
full_file_path = os.path.join(directory, filename)
# Defining the multipart payload
# Fields expecting files use a tuple: (filename, file_object, content_type)
# Fields expecting simple data use a tuple: (None, value)
form_data = {
'source_id': (None, 'sensor_unit_01'),
'captured_image': (filename, open(full_file_path, 'rb'), mime_type),
'capture_time': (None, '2023-11-15 14:30:00')
}
# Execute the request using the 'files' parameter
# The context manager ensures the file handle is closed properly
with open(full_file_path, 'rb') as file_handle:
form_data['captured_image'] = (filename, file_handle, mime_type)
response = requests.post(url=api_endpoint, files=form_data)
return response.()
For scenarios requiring manual control over the multipart/form-data encoding or when integrating with libraries that need pre-encoded bodies, urllib3 can be used. This method involves reading the file content into memory, defining the fields, and generating the raw byte string and the corresponding Content-Type header.
from urllib3 import encode_multipart_formdata
import requests
def upload_text_document(file_location, access_token):
target_url = "https://api.service.example/docs/upload"
# Read file content as text
with open(file_location, mode="r", encoding="utf-8") as f_obj:
content_data = f_obj.read()
# Construct the field dictionary for encoding
multipart_fields = {
"document_file": (os.path.basename(file_location), content_data),
"category": "reports"
}
# Manually encode the data to get the body and Content-Type header
encoded_body, content_type_header = encode_multipart_formdata(multipart_fields)
# Set up headers including the dynamically generated Content-Type
request_headers = {
"Content-Type": content_type_header,
"Authorization": f"Bearer {access_token}"
}
# Send the request using the encoded body in the 'data' parameter
server_response = requests.post(url=target_url, data=encoded_body, headers=request_headers)
return server_response.()