Upload an image to Blob Storage from a stream (in Python)

Viewed 3496

I need to upload an image generated from Python to Azure Blob Storage without saving it locally. At this point I generate an image, save it locally and upload it to the storage (see code below) but I need to run it for a large number of images and need it not to be dependent on the local storage.

I have tried saving it in the form of stream (in particular Bytes stream) as the uploading appears to be working with a stream as well (sorry if it is a naive approach, I am not so experienced in Python) but I have no idea how to use it in the uploading process. If I use it the same way as when opening local file, it uploads an empty file.

I am using azure-storage-blob version 12.2.0. I have noticed that in previous version of azure-storage-blob there was a possibility to upload from stream (in paticular BlockBlobService.get_blob_to_stream) but I cannot find it in this version and I cannot downgrade the package due to some dependencies.

Any help very much appreciated.

import matplotlib.pyplot as plt
import numpy as np
from io import BytesIO
from azure.storage.blob import ContainerClient

# create some mock data
t = np.arange(0.01, 10.0, 0.01)
data1 = np.sin(2 * np.pi * t)

# plot it
fig, ax1 = plt.subplots()
ax1.set_xlabel('time (s)')
ax1.set_ylabel('exp')
ax1.plot(t, data1)

# save it locally
plt.savefig("example.png")

# create a blob client and upload the file
container_client = ContainerClient.from_container_url(container_SASconnection_string)
blob_client = container_client.get_blob_client(blob = "example.png")

with open("example.png") as data:
    blob_client.upload_blob(data, blob_type="BlockBlob")


# ALTERNATIVELY, instead of saving locally save it as an image stream
fig, ax1 = plt.subplots()
ax1.set_xlabel('time (s)')
ax1.set_ylabel('exp')
ax1.plot(t, data1)

image_stream = BytesIO()
plt.savefig(image_stream)

# but this does not work (it uploads an empty file)
# blob_client.upload_blob(image_stream, blob_type="BlockBlob")
1 Answers

What you have to to do reset the stream's position to 0 and then you can upload it directly to blob storage without saving it to a local file first.

Here's the code I wrote:

import matplotlib.pyplot as plt
import numpy as np
from io import BytesIO
from azure.storage.blob import ContainerClient

# create some mock data
t = np.arange(0.01, 10.0, 0.01)
data1 = np.sin(2 * np.pi * t)

# plot it
fig, ax1 = plt.subplots()
ax1.set_xlabel('time (s)')
ax1.set_ylabel('exp')
ax1.plot(t, data1)

image_stream = BytesIO()
plt.savefig(image_stream)
# reset stream's position to 0
image_stream.seek(0)

# upload in blob storage
container_client = ContainerClient.from_container_url(container_SASconnection_string)
blob_client = container_client.get_blob_client(blob = "example.png")
blob_client.upload_blob(image_stream.read(), blob_type="BlockBlob") 
Related