2015-11-20 105 views
4

我想从服务器端向客户端发送图像文件。我正在使用瓶框架。send_file()被调用时返回文本文档而不是图像

但问题是每当我调用send_file()的路由时,响应返回的是一个文件。当我点击这个文件gedit打开它没有文件。这意味着它必须是写入文本文件。

我提到烧瓶文档为send_file()

以下是我在代码正在做的:

@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) 

每当我加载localhost:5000/try文件被下载,但并不是说我要下载的图像文件。

错误我在我的终端得到的是AttributeError: 'Response' object has no attribute 'read' error

这是什么问题。上面的代码片段中是否缺少任何内容?

+0

你没收到'AttributeError的: '响应' 对象有没有属性“read''错误? –

+0

你需要使用'send_file(resp.content ...)'吗? –

+0

@SimonMᶜKenzie如果我使用'resp.content'同样的事情发生 –

回答

10
  1. resprequests.models.Response对象,而不是字符串也不字节:

    >>> 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'> 
    
  2. Flask.send_file()发送文件


所以首先在你需要使用resp.content来获取对象的内容,它会返回字节对象(顺便说一句,resp.text返回字符串对象。 如果”始终使用.content重新下载图像,视频或其他非文本内容)。

>>> 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'> 

请检查the document了解更多详情。


然后,因为Flask.send_file()发送文件,所以你需要将图像写入到文件在发送前。

但是既然你不需要在你的服务器上使用这个映像,我建议在这种情况下使用​​,那么在你发送它之后你不需要删除那个映像。如果您发送的是文本文件,请注意使用io.StringIO

例如:

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) 

但是,如果你想将图像写入到文件,并传送话,相信你也可以做到这一点。我们可以使用tempfile.NamedTemporaryFile()创建一个临时文件而不是只创建一个文件以避免重写您的重要文件。

从文件:

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 a with statement, just like a normal file.

例如:

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) 
+0

你解释我喜欢Iam5。非常好的解释。谢谢你 –

+0

@SurajPalwe:没问题,很高兴我可以帮助:) –

+1

我会改变这两种解决方案的顺序。首先将图像写入文件(您也需要在某个时候删除它)..并不是一个好主意,并且**特别是**不具有硬编码文件名,而不是由'tempfile'模块创建的文件。这只是要求一次有多个请求出现问题。 – ThiefMaster

相关问题