【问题标题】:Return data on HTTP upload to sanic server将 HTTP 上传的数据返回到 sanic 服务器
【发布时间】:2019-03-26 00:53:55
【问题描述】:

我正在尝试将数据上传到sanic 网络服务器。为此,我使用 curl 发出 POST 请求。我尝试在 POST 请求后返回一些数据。这背后的基本原理是返回一些现在代表服务器端上传的 ID。但这似乎不起作用。现在我想知道:我的程序错了吗? curl 不写输出吗?或者这是sanic 中的错误?有人可以在这里帮助我吗?谢谢!

这是 Python 程序:

import signal
import asyncio
import uvloop

import sanic

app = sanic.Sanic(__name__)
loop = asyncio.get_event_loop()
server = app.create_server(host="localhost", port=3002)
task = asyncio.ensure_future(server)

@app.post("/testUpload", stream=True)
async def api_testUpload(request):

    async def doStream(response):
        while True:
            body = await request.stream.get()
            if body is None:
                break

            sanic.response.json({
                "result": "good!"
            })

    return sanic.response.stream(doStream)

signal.signal(signal.SIGINT, lambda s, f: loop.stop())
try:
    loop.run_forever()
except:
    loop.stop()

您可以像这样调用curl

curl -v --data-binary "@somefile.data" http://localhost:3002/testUpload

这是curl 写入 STDOUT 的内容:

*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 3002 (#0)
> POST /testUpload HTTP/1.1
> Host: localhost:3002
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Length: 334504
> Content-Type: application/x-www-form-urlencoded
> Expect: 100-continue
> 
< HTTP/1.1 200 OK
< Keep-Alive: 5
< Transfer-Encoding: chunked
< Content-Type: text/plain; charset=utf-8
< 
* Done waiting for 100-continue
* We are completely uploaded and fine
* Connection #0 to host localhost left intact

如您所见,生成了text/plain 响应。这应该是带有我的数据的application/json,不是吗?

【问题讨论】:

    标签: python http file-upload sanic


    【解决方案1】:

    这不是正确的做法。 sanic API 在这里不能直观地工作。为了在接收到发送的字节后写入数据,您必须在流功能doStream() 中这样做:

    await response.write(json.dumps({
        "result": "good!"
    }))
    

    【讨论】:

      【解决方案2】:

      如果我理解您的问题,那么您根本不需要直播。在我看来,您正在尝试做的是:

      • 上传文件
      • 处理文件并做一些事情
      • 返回响应以表示某事已完成

      假设是这种情况,那么您根本不需要流式传输。

      import sanic
      
      app = sanic.Sanic(__name__)
      
      def do_something(file):
          print(f'doing something to {file.name}')
      
      @app.post("/testUpload")
      async def api_testUpload(request):
          myfile = request.files.get('myfile')
      
          do_something(myfile)
      
          return sanic.response.json({
              'body': myfile.body,
              'name': myfile.name,
              'type': myfile.type,
          })
      
      app.run(host='localhost', port=3002, auto_reload=True)
      

      然后您可以使用文件访问您的端点...

      curl -i -F "myfile=@/tmp/somefile.txt" http://localhost:3002/testUpload
      

      您应该在日志中看到:

      [2018-10-25 10:09:56 +0300] [16051] [INFO] Goin' Fast @ http://localhost:3002
      [2018-10-25 10:09:56 +0300] [16055] [INFO] Starting worker [16055]
      doing something to somefile.txt
      [2018-10-25 10:09:59 +0300] - (sanic.access)[INFO][127.0.0.1:39306]: POST http://localhost:3002/testUpload  200 62
      

      你的回报

      HTTP/1.1 200 OK
      Connection: keep-alive
      Keep-Alive: 5
      Content-Length: 62
      Content-Type: application/json
      
      {"body":"FOOBAR\n","name":"somefile.txt","type":"text\/plain"}
      

      现在,我想如果您正在上传一个文件,并且您想在该请求或其他请求发生时流式传输该上传的响应,那将是一个不同的问题。

      我希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-26
        • 2012-08-26
        • 2015-07-11
        • 2016-06-09
        • 1970-01-01
        • 2017-09-27
        • 2018-02-20
        • 2012-11-01
        相关资源
        最近更新 更多