Python:从RestAPI

时间:2018-08-03 03:57:35

标签: python flask python-requests

第三方RestAPI提供了服务器日志文件,此刻我们正在使用curl命令之类的文件下载日志文件

curl -H "X-Auth-Token: XXXXXXXXXXXXXXXXXXXXXXXXXX" https://host_address/api/v3.0/admin/logs -o logs.zip

但是我试图使用Flask / Python创建简单的仪表板,

这是我的路线的Python / Flask代码:

@app.route('/download/server/logs')
def download_log():
    import requests
    from flask import send_file
    res = requests.get('http://<rest_api_host>/v1.2/admin/logs', stream=True)
    return send_file(
        res.content,
        attachment_filename='console_log.zip',
        mimetype='application/zip'
    )

但是当我从浏览器中访问该URL时,出现以下错误,

Traceback (most recent call last):
...
...
...
  File "/Users/admin/Documents/project/__init__.py", line 940, in download_console_logs
    res.content,
  File "/Users/admin/Documents/project/venv3/lib/python3.6/site-packages/requests/models.py", line 823, in content
    self._content = bytes().join(self.iter_content(CONTENT_CHUNK_SIZE)) or bytes()
  File "/Users/admin/Documents/project/venv3/lib/python3.6/site-packages/requests/models.py", line 745, in generate
    for chunk in self.raw.stream(chunk_size, decode_content=True):
  File "/Users/admin/Documents/project/venv3/lib/python3.6/site-packages/urllib3/response.py", line 436, in stream
    data = self.read(amt=amt, decode_content=decode_content)
  File "/Users/admin/Documents/project/venv3/lib/python3.6/site-packages/urllib3/response.py", line 384, in read
    data = self._fp.read(amt)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 449, in read
    n = self.readinto(b)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 497, in readinto
    self._close_conn()
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 403, in _close_conn
    fp.close()
AttributeError: 'NoneType' object has no attribute 'close'

我使用PyCharm放置了断点/调试器,能够看到res.content中包含二进制数据,但是我无法弄清楚这里出了什么问题。

这是简单的图表,它解释了我正在尝试做的事情, enter image description here

更新:答案:我采用了以下方法,它以非常有效的方式解决了我的问题。

@app.route('/download/server/logs')
def download_log():
    import requests
    from flask import Reponse
    res = requests.get('http://<rest_api_host>/v1.2/admin/logs', stream=True)
    return Response(
        res.iter_content(chunk_size=1024),
        direct_passthrough=True
    )

4 个答案:

答案 0 :(得分:1)

从本地文件夹下载

def download_Object():
    try:
        srcFileName="bulk_file.zip"
        with open(srcFileName, 'wb') as f:
            f.write(srcFileName)
    except Exception as e:
        print(e)

答案 1 :(得分:1)

try:
    srcFileName="filename"
    with open(srcFileName, 'wb') as f:
        f.write(srcFileName)
except Exception as e:
    print(e)

答案 2 :(得分:0)

我不确定您是否给出了正确的错误消息。但是我认为,如果您将字符串传递给send_file()方法,它将无法正常工作。您需要改为传递二进制数据。

如果将res.content包装在io.BytesIO()内并将其传递给send_file()方法,我相信它应该可以工作。

例如:

@app.route('/download/server/logs')
def download_log():
    import requests
    from flask import send_file
    import io
    res = requests.get('http://<rest_api_host>/v1.2/admin/logs', stream=True)
    return send_file(
        io.BytesIO(res.content),
        attachment_filename='console_log.zip',
        mimetype='application/zip'
    )

希望有帮助!

答案 3 :(得分:0)

如果要下载文件,请尝试烧瓶的Response方法:

import requests
from flask import Response
@app.route('/download/server/logs')
def download_log():
res = requests.get('http://<rest_api_host>/v1.2/admin/logs')
return Response(res.content,headers = dict(res.headers))