【问题标题】:POSTing and rerouting a file through Flask通过 Flask 发布和重新路由文件
【发布时间】:2018-02-11 01:59:43
【问题描述】:

我目前在单独的 Docker 容器中运行一个 Flask-RESTful 应用程序和一个 Apache Tika 服务器。 Flask 服务器在容器和主机的 5000 端口上提供服务,而 Tika 服务器在 9998 上提供服务。

我希望能够将客户端上传到 Flask 服务器的文件传递到 Tika 服务器,以便我可以提取文档的文本。但是,我似乎无能为力。我尝试读取文件的所有方法都失败了。有谁知道我做错了什么?

以下工作在 Python 中用于访问 Tika 服务器:

requests.request('PUT', 'http://localhost:9998/rmeta/text', data=open('test_doc.docx', 'rb'), headers={}).text

但是,尝试像这样通过 Flask 服务器进行路由会中断:

requests.request('post', 'http://localhost:5000/index', files={'file': open('test_doc.docx', 'rb')}, headers={}).text

app/__init__.py

class Index(MethodView):
    def post(self):
        #Load in file
        parse = reqparse.RequestParser()
        parse.add_argument('file', type=werkzeug.datastructures.FileStorage, location='files')
        args = parse.parse_args()
        uploadedFile = args['file']
        filename = secure_filename(uploadedFile.filename)

        #Create temporary file
        tmpfile = TemporaryFile()
        tmpfile.write(uploadedFile.stream.read())

        #Extract text
        data = tika.extract_text(tmpfile)
        tmpfile.close()
        return data

app/tika/__init__.py

import json
import requests

class Tika:
    def __init__(self, endpoint):
        self.endpoint = endpoint

    def extract_text(self, filedata):
        response = requests.request('put', self.endpoint, data=filedata, headers={}).json()
        try:
            return response[0]["X-TIKA:content"]
        except:
            return "ERROR"

追溯

Traceback (most recent call last):
  File "/opt/conda/envs/SDL/lib/python3.5/site-packages/flask/app.py", line 1997, in __call__
    return self.wsgi_app(environ, start_response)
  File "/opt/conda/envs/SDL/lib/python3.5/site-packages/flask/app.py", line 1985, in wsgi_app
    response = self.handle_exception(e)
  File "/opt/conda/envs/SDL/lib/python3.5/site-packages/flask_restful/__init__.py", line 273, in error_router
    return original_handler(e)
  File "/opt/conda/envs/SDL/lib/python3.5/site-packages/flask/app.py", line 1540, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/opt/conda/envs/SDL/lib/python3.5/site-packages/flask/_compat.py", line 32, in reraise
    raise value.with_traceback(tb)
  File "/opt/conda/envs/SDL/lib/python3.5/site-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/opt/conda/envs/SDL/lib/python3.5/site-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/opt/conda/envs/SDL/lib/python3.5/site-packages/flask_restful/__init__.py", line 273, in error_router
    return original_handler(e)
  File "/opt/conda/envs/SDL/lib/python3.5/site-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/opt/conda/envs/SDL/lib/python3.5/site-packages/flask/_compat.py", line 32, in reraise
    raise value.with_traceback(tb)
  File "/opt/conda/envs/SDL/lib/python3.5/site-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/opt/conda/envs/SDL/lib/python3.5/site-packages/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/opt/conda/envs/SDL/lib/python3.5/site-packages/flask_restful/__init__.py", line 480, in wrapper
    resp = resource(*args, **kwargs)
  File "/opt/conda/envs/SDL/lib/python3.5/site-packages/flask/views.py", line 84, in view
    return self.dispatch_request(*args, **kwargs)
  File "/opt/conda/envs/SDL/lib/python3.5/site-packages/flask/views.py", line 149, in dispatch_request
    return meth(*args, **kwargs)
  File "/app/__init__.py", line 109, in post
    data = get_clean_text(tika.extract_text(tmpfile))
  File "/app/tika/__init__.py", line 16, in extract_text
    response = requests.request('put', self.endpoint, data=filedata, headers={}).json()
  File "/opt/conda/envs/SDL/lib/python3.5/site-packages/requests/models.py", line 885, in json
    return complexjson.loads(self.text, **kwargs)
  File "/opt/conda/envs/SDL/lib/python3.5/json/__init__.py", line 319, in loads
    return _default_decoder.decode(s)
  File "/opt/conda/envs/SDL/lib/python3.5/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/opt/conda/envs/SDL/lib/python3.5/json/decoder.py", line 357, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

这与我尝试将文件传递到服务器并对其进行解码的方式有关,但对于我的生活,我无法弄清楚。任何和所有的帮助将不胜感激。

【问题讨论】:

  • 将此response = requests.request('put', self.endpoint, data=filedata, headers={}).json() 更改为response = requests.request('put', self.endpoint, data=filedata, headers={}).text 并打印返回值。您很可能会收到 html 响应形式的错误。你需要调查一下

标签: python web-services http curl flask


【解决方案1】:

问题是没有数据被传递到tika.extract_text()。这是因为tmpfile.write(uploadedFile.stream.read()) 将上传的数据写入临时文件,之后文件指针位于文件末尾。这个文件句柄然后被传递给tika.extract_text(tmpfile),但是,因为文件指针在文件的末尾,任何读取都将返回一个空字符串,因此没有任何东西被传递到您的 tika 服务器。

您可以通过在将临时文件交给tika.extract_text()之前查找临时文件的开头来轻松解决此问题:

    #Create temporary file
    tmpfile = TemporaryFile()
    tmpfile.write(uploadedFile.stream.read())
    tmpfile.seek(0)    # reposition file pointer to the start of the file

    data = tika.extract_text(tmpfile)

在您发布的代码中,我不清楚您为什么需要使用临时文件。您可以简单地将上传的数据直接传递给 tika 服务器:

from flask import Flask, request
from flask.views import MethodView
from flask.json import jsonify

app = Flask(__name__)

class Index(MethodView):
    def post(self):
        uploaded_file = request.files.get('file')
        if uploaded_file:
            data = tika.extract_text(uploaded_file)
        else:
            data = {'error': 'Missing upload file'}

        return jsonify(data)

app.add_url_rule('/', view_func=Index.as_view('/'))

app.run()

【讨论】:

    猜你喜欢
    • 2022-12-12
    • 2018-12-11
    • 2015-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多