Getting image from Firebase and creating stripe.File - python

I am trying transfer a file to Stripe from a firebase database using the stripe.File.create() method. Here is the code that I am using:
file_url = storage.child("/path/to/file").get_url(token=None)
response = requests.get(file_url, stream=True)
img = Image.open(BytesIO(response.content))
stripe.File.create(
purpose="identity_document",
file=img
)
But when I run this code I get:
Request req_E7fskNVgpHHlRm: Invalid hash
I believe I am getting the correct image from firebase, since I can run the following line and get the image saved to my local drive:
img.save("test.jpg")
But Stripe doest not seem to like the file format that I am giving it. I believe the file has to be supplied in binary mode, so perhaps I simply need to do edit the line img = Image.open(BytesIO(response.content)) to get the file in binary mode.
Any feedback is appreciated.

I figured it out. img = Image.open(BytesIO(response.content)) creates a JpegImageFile object, which is an image. But Stripe is expecting a file, something like io.BufferedReader object. So Stripe is saying that you are supplying an image, when really it just wants a file. To fix the issue, just change the img = line to:
imgFile = BytesIO(response.content)

Related

How to download large file from Cloud Run in Django

I have Django project on Cloud Run. When I download small file from page which has below code.
def download_view(request,pk):
file_path = f'media/{pk}.mp3'
name = f'{pk}.mp3'
with open(file_path, 'rb') as f:
response = HttpResponse(f.read(), content_type='audio/wav')
response['Content-Disposition'] = f'attachment; filename={name}'
return response
It's works fine. However, when I download a file (50MB). I got this picture's error.
Cloud run's log is like this. I couldn't find any log of traceback.
2021-05-06 12:00:35.668 JSTGET500606 B66 msChrome 72 https://***/download/mp3/2500762/
2021-05-06 11:49:49.037 JSTGET500606 B61 msChrome 72 https://***/download/mp3/2500645/
I'm not sure. Is this error related with download error.
2021-05-06 16:48:32.570 JSTResponse size was too large. Please consider reducing response size.
I think this is upload file size error. So this is not related with this subject of download error.
When I run Django at local, then download same 50MB file. I can download it. I think this download error related with Cloud run. It's stop after request/response. So I think this error coused by Cloud Run. Which was stoped, when I'm still downloading file.
I don't know how to solve this download error. If you have any solution, please help me!
The Cloud Run HTTP request/response size is limited to 32Mb. Use a multipart/form-data to send chunks of your big file and not the whole file directly.
Thank you #guillaume blaquiere! I solved download error. I post my code for othres.
def _file_iterator(file, chunk_size=512):
with open(file, 'rb') as f:
while True:
c = f.read(chunk_size)
if c:
yield c
else:
break
def download_view(request,pk):
file_path = f'media/{pk}.mp3'
file_name = f'{pk}.mp3'
response = StreamingHttpResponse(_file_iterator(file_path))
response['Content-Type'] = 'audio/mpeg'
response['Content-Disposition'] = f'attachment;filename="{file_name}"'
return response
I think StreamingHttpResponse is key point of this problem. It's return big file by chunks. It dose not over Cloud Run's limit.
When I used multipart/form-data for Content-Type, I could download file. But it's couldn't open on smart phone, because It couldn't select application. When I download on PC, it's can't show audio file icon. We should select exact content type.

Cannot open Image file got from request.files.get()

I am trying to make a face recognition API with Flask and deepface library.
But I am not able to open the image it's giving me different errors. Please give me a solution.
Code:
#app.route('/detect', methods=['POST'])
def recognize():
image_path = request.files.get('image')
try:
analysis = DeepFace.analyze(image_path)
return jsonify(analysis)
except Exception as e:
return jsonify({'error': str(e)})
error
"error": "object of type 'FileStorage' has no len()"
Tried to open the image
with open(image_path, 'r') as image:
analysis = DeepFace.analyze(image)
return jsonify(analysis)
I get the error
{"errors": "expected str, bytes or os.PathLike object, not FileStorage"}
I think image_path holds object of type FileStorage which knows location of a file and does not hold actual image data. First you need to load that image file and then try to analyze it.
A werkzeug FileStorage object has several methods as I've documented in another answer.
Sounds like you need to save the image to a temporary location first, then do the analysis.
I would create a directory called uploads on your server, then set this in the app config:
app.config['UPLOAD_FOLDER'] = 'uploads'
Then in your route, use the uuid.uuid4 function to create a temporary filename. Something like:
from uuid import uuid4
#app.route('/detect', methods=['POST'])
def recognize():
tmp_fname = os.path.join(app.config['UPLOAD_FOLDER'], uuid4().__str__())
image = request.files['image']
image.save(tmp_fname)
try:
analysis = DeepFace.analyze(tmp_fname)
return jsonify(analysis)
except Exception as e:
return jsonify({'error': str(e)})
This leaves the saved images on the filesystem, so you may wish to do some cleanup on this directory, or do something like os.remove('tmp_fname') after running the analysis.
I'm not sure whether Deepface.analyze accepts a stream as its first argument. The README suggests it only accepts a filename as a string. You could try doing Deepface.analyze(image.stream) to avoid having to deal with saving the temporary file (keep everything in memory instead), but this may not be supported.

Use Python to get image in Zapier

I am trying to use a Python code step to download an image in Zapier. Here is some sample code (but it doesn't seem to work):
r = requests.get('https://dummyimage.com/600x400/000/fff')
img = r.raw.read()
return {'image_data': img}
The error I get is
Runtime.MarshalError: Unable to marshal response: b'' is not JSON serializable
Does anyone know how I can use requests in a Python code step in Zapier to get an image? (I am trying to get the image and save it to Dropbox.)
THANKS.
It looks like you need a json serializable object and not a binary object.
One way to convert your image to a string is to use base64 and then encode it:
Make the image serializable:
r = requests.get('https://dummyimage.com/600x400/000/fff')
img_serializable = base64.b64encode(r.content).decode('utf-8')
# check with json.dumps(img_serializable)
Now return {'image_data': img_serializable} should not give errors.
Recover image from string and save to file:
with open("imageToSave.png", "wb") as f:
f.write(base64.decodebytes(img_serializable.encode('utf-8')))
The same using codecs, that is part of the standard Python library:
r = requests.get('https://dummyimage.com/600x400/000/fff')
content = codecs.encode(r.content, encoding='base64')
img_serializable = codecs.decode(content,encoding='utf-8')
type(img_serializable)
# Out:
# str
with open("imageToSave3.png", "wb") as f:
f.write(codecs.decode(codecs.encode(img_serializable, encoding='utf-8'), \
encoding='base64'))

How to save image using Python

I have an image file decoded by base64.
Now, I want to save the image file to the specified directory.
the directory is described as image_dir_path
image_dir_path = '/images/store/'
image_file = base64.b64decode(image_file)
How can I save the image_file to image_dir_path?
I tried shutil.copy(image_file, image_dir_path), but it doesn't work for my case.
I'm sorry I coundn't find the question like this.
You can write any content to a file with a file object and its write method. As an example, let's grab some base64 encoded data from the web:
import base64, urllib
decoded = base64.b64decode(urllib.urlopen("http://git.io/vYT4p").read())
with open('/tmp/31558315.png', 'w') as handle:
handle.write(decoded)
You should be able to open the file under /tmp/31558315.png as a regular image.

How to convert blob into byteArray in flask python?

A customer sends a multipart file to me, I read it with:
blob = request.files['file'].read()
I have a blob file in hand. Now I have to send this file with requests like open('file.png', 'rb'). How can I convert blob to something like rb mode. With open I could not open blob directly.
The below code did not work:
opened_file = open(request.files['file'], 'rb')
And I got the following error:
TypeError: coercing to Unicode: need string or buffer, FileStorage found
Is there a way to do that without saving it on file system? I send my requests to somewhere else:
files = dict({'file': byteArrayFile})
r = requests.post(self.url, files=files, headers=headers)
request.files['file'] is already a file-like object (it's a FileStorage instance), so you can use that directly; you don't need to open it.
r = requests.post(self.url, files={"file": request.files["file"]}, headers=headers)
You can think of a file-like object as an open file. They behave the same way.
try using
from PIL import Image
import requests
from io import BytesIO
response = requests.get(url)
img = Image.open(BytesIO(response.content))
it worked for me and for testing if you wish to have a look on the images try
img.show()
If your image is stored in a Blob format (i.e. in a database) you can use the same technique explained by Billal Begueradj to convert your image from Blobs to a byte array.
In my case, I needed my images where stored in a blob column in a db table:
def select_all_X_values(conn):
cur = conn.cursor()
cur.execute("SELECT ImageData from PiecesTable")
rows = cur.fetchall()
return rows
I then created a helper function to change my dataset into np.array:
X_dataset = select_all_X_values(conn)
imagesList = convertToByteIO(np.array(X_dataset))
def convertToByteIO(imagesArray):
"""
# Converts an array of images into an array of Bytes
"""
imagesList = []
for i in range(len(imagesArray)):
img = Image.open(BytesIO(imagesArray[i])).convert("RGB")
imagesList.insert(i, np.array(img))
return imagesList
After this, I was able to use the byteArrays in my Neural Network.
plt.imshow(imagesList[0])

Categories