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
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.
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.
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'))
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.
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])