I want to send an image file from server side to client side. I am using flask framework.
But the problem is whenever I call the route in which send_file()
is, the response return is an File. When I click this file gedit
opens it with nothing in that file. That means it must be text file written.
I referred the flask docs for send_file()
.
Here is what I am doing in the code:
@app.route('/try')
def trial():
todown = 'https://igcdn-photos-e-a.akamaihd.net//hphotos-ak-xaf1//t51.2885-15//e35//12093691_1082288621781484_1524190206_n.jpg'
resp = requests.get(todown)
return send_file(resp,mimetype="image/jpeg",attachment_filename="img.jpg",as_attachment=True)
Whenever I load localhost:5000/try
a file is downloaded but not the image file that I want to download.
Error I am getting in my terminal is AttributeError: 'Response' object has no attribute 'read' error
.
What must be the problem. Is anything missing in this above snippet?
resp
is a requests.models.Response
object, not string nor bytes:
>>> import requests
>>> todown = 'https://igcdn-photos-e-a.akamaihd.net//hphotos-ak-xaf1//t51.2885-15//e35//12093691_1082288621781484_1524190206_n.jpg'
>>> resp = requests.get(todown)
>>> resp
<Response [200]>
>>> type(resp)
<class 'requests.models.Response'>
Flask.send_file()
sends a file.
So first at all you need use resp.content
to get the content of the object, it'll return bytes object (and by the way, resp.text
return string object.
Always use .content
if you're downloading an image, video, or other non-text things).
>>> import requests
>>> todown = 'https://igcdn-photos-e-a.akamaihd.net//hphotos-ak-xaf1//t51.2885-15//e35//12093691_1082288621781484_1524190206_n.jpg'
>>> resp = requests.get(todown)
>>> type(resp.content)
<class 'bytes'>
Please check the document for more details.
Then, because Flask.send_file()
send a file, so you need write the image into a file before you send it.
But since you don't need use this image on your server anyway, I'd suggest use io.BytesIO
in this case, then you don't need delete that image after you sent it. And note that use io.StringIO
if you're sending a text file.
For example:
import requests
from io import BytesIO
from flask import Flask, send_file
app = Flask(__name__)
@app.route('/')
def tria():
todown = 'https://igcdn-photos-e-a.akamaihd.net//hphotos-ak-xaf1//t51.2885-15//e35//12093691_1082288621781484_1524190206_n.jpg'
resp = requests.get(todown)
return send_file(BytesIO(resp.content), mimetype="image/jpeg", attachment_filename="img2.jpg", as_attachment=True)
app.run(port=80, debug=True)
However, if you want write the image into a file and send it then, sure you can also do it. We can use tempfile.NamedTemporaryFile()
to create a tempfile instead of just create a file to avoid rewrite your important files.
From the document:
This function operates exactly as
TemporaryFile()
does, except that the file is guaranteed to have a visible name in the file system (on Unix, the directory entry is not unlinked).That name can be retrieved from the
name
attribute of the file object. Whether the name can be used to open the file a second time, while the named temporary file is still open, varies across platforms (it can be so used on Unix; it cannot on Windows NT or later). If delete is true (the default), the file is deleted as soon as it is closed.The returned object is always a file-like object whose
file
attribute is the underlying true file object. This file-like object can be used in awith
statement, just like a normal file.
For example:
import tempfile
import requests
from flask import Flask, send_file
app = Flask(__name__)
@app.route('/')
def tria():
todown = 'https://igcdn-photos-e-a.akamaihd.net//hphotos-ak-xaf1//t51.2885-15//e35//12093691_1082288621781484_1524190206_n.jpg'
resp = requests.get(todown)
with tempfile.NamedTemporaryFile() as f:
# create a file-like object use `NamedTemporaryFile()` and `with`
# as the basic usage which said in the document
f.write(resp.content)
# write the content of the image into it
return send_file(f.name, mimetype="image/jpeg",
attachment_filename="img2.jpg", as_attachment=True)
# `f.name` is the temp file's filename
app.run(port=80, debug=True)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With