【问题标题】:Tornado: testing multipart request using AsyncHTTPTestCaseTornado:使用 AsyncHTTPTestCase 测试多部分请求
【发布时间】:2018-04-12 08:04:38
【问题描述】:

我正在为使用多部分请求的用户上传文件编写 API。我看到 Tornado 4.5 版已经支持多部分请求。但在那之后,我想测试这个 API。

我的问题是:

  • 如何在 Tornado 上测试多部分请求。我有很多参考资料,但我找不到有用的资源。
  • 如果无法在 Tornado 中执行此操作,我如何提出多部分请求,以便可以与 tornado 的 AsyncHTTPTestCase 一起使用。

谢谢

【问题讨论】:

    标签: tornado multipartform-data


    【解决方案1】:

    Tornado 没有对发出多部分请求的内置支持。你会 必须手动执行多部分请求。

    让我们先看看multipart/form-data 请求的样子。

    示例表格:

    <form method="POST" enctype="multipart/form-data">
        <input type="text" name="field1">
        <input type="file" name="field2">
    
        <input type="submit">
    </form>
    

    如果您在field1 中输入Hello 并为field2 选择一个名为myfile.png 的文件, HTTP 请求将如下所示:

    POST /url HTTP/1.1
    Content-Type: multipart/form-data; boundary="boundary"
    
    --boundary
    Content-Disposition: form-data; name="field1"
    
    Hello
    --boundary
    Content-Disposition: form-data; name="field2"; filename="myfile.png"
    Conent-Type: image/png
    
    <binary content of myfile.png>
    --boundary--
    

    您所要做的就是编译一个类似的请求。


    在给你举个例子之前,让我先让你明白一点, 如果您还不知道 - 在上面的原始 HTTP 请求示例中,最后 每行都有这些字符-\r\n。它们在这里不可见,但 它们存在于实际的 HTTP 请求中。甚至空白行都有\r\n 出现的字符。

    了解这一点很重要。如果您要手动编译 HTTP 请求,您将 必须在每行末尾添加\r\n 字符。

    让我们来看例子。

    class MyTestCase(AsyncHTTPTestCase):
        def test_something(self):
            # create a boundary
            boundary = 'SomeRandomBoundary'
    
            # set the Content-Type header
            headers = {
                'Content-Type': 'multipart/form-data; boundary=%s' % boundary
            }
    
            # create the body
    
            # opening boundary
            body = '--%s\r\n' % boundary 
    
            # data for field1
            body += 'Content-Disposition: form-data; name="field1"\r\n'
            body += '\r\n' # blank line
            body += 'Hello\r\n'
    
            # separator boundary
            body += '--%s\r\n' % boundary 
    
            # data for field2
            body += 'Content-Disposition: form-data; name="field2"; filename="myfile.png"\r\n'
            body += '\r\n' # blank line
            # now read myfile.png and add that data to the body
            with open('myfile.png', 'rb') as f:
                body += '%s\r\n' % f.read()
    
            # the closing boundary
            body += "--%s--\r\n" % boundary
    
    
            # make a request
            self.fetch(url, method='POST', headers=headers, body=body)
    

    上面的代码非常基础。如果你有多个文件和参数,你应该 考虑为此编写一个单独的函数并使用for 循环。 Click here 获取 Tornado 的 github 存储库中的示例代码。

    【讨论】:

    • 真的非常感谢 :D 非常棒的帖子。我在其他地方找不到本教程:D
    • 只是有一个小问题,因为在多部分请求中,如果文件很大,我们必须以某种方式流式传输请求。所以我们可以假设我们只发出一个这样的请求就可以处理大文件吗?谢谢。
    • @TrầnKimDự 不,上面的代码对于大文件是不安全的。但是here's an example(参见突出显示的代码)用于分块流式传输大文件。如果您真的不需要multipart/form-data,即您只想上传单个文件,请考虑使用PUT 而不是POST 方法。这会容易得多。
    • 我明白了。非常感谢 :D 这真是一个很棒的帖子 :D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-01
    • 1970-01-01
    • 2014-03-15
    • 2020-11-14
    相关资源
    最近更新 更多