如何使用 Playwright 在 Python 中 PUT 多部分表单数据?

问题描述 投票:0回答:1

我正在尝试使用 Playwright 通过 Python API 来 PUT 多部分表单数据。 这是相关的文档

但是,尚不清楚如何构造 multipart 参数。 文档说:

multipart: Dict[str, str|float|bool|[ReadStream]|Dict] (optional)

   name: str
   File name

   mimeType: str
   File type

   buffer: bytes
   File content

提供一个对象,该对象将使用 multipart/form-data 编码序列化为 html 表单,并作为此请求正文发送。如果指定此参数,内容类型标头将设置为 multipart/form-data,除非明确提供。文件值可以作为 fs.ReadStream 或作为包含文件名、mime 类型及其内容的类文件对象传递。

因此,我们向它传递一个带有

str
键和
str
float
bool
ReadStream
Dict
值的字典。但是我们应该使用什么键呢?另外,如何从 Python 脚本传递
fs.ReadStream
(一个 JavaScript 对象)?看起来按键应该是
'name'
'mimeType'
'buffer'
。但是,使用
nc -l -p 8080
检查生成的 HTTP 请求表明,为多部分字典中的每个键创建了一个新的表单部分。

我本质上是在尝试复制以下

curl
命令:

curl 'localhost:8080' -X PUT --form file='@test.zip;filename=test.zip;type=application/x-zip-compressed'

假设您之前运行过

nc -l -p 8080 | less
,您将看到以下 HTTP 请求:

PUT / HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.81.0
Accept: */*
Content-Length: 380
Content-Type: multipart/form-data; boundary=------------------------f3dde3ddff901cd3

--------------------------f3dde3ddff901cd3
Content-Disposition: form-data; name="file"; filename="test.zip"
Content-Type: application/x-zip-compressed

PK^C^D
^@^@^@^@^@<D1>`xW^N<93>ESC<91>
^@^@^@
^@^@^@^H^@^\^@test.txtUT        ^@^C^Z<F7>_e^Z<F7>_eux^K^@^A^D<E8>^C^@^@^D<E8>^C^@^@Test file
PK^A^B^^^C
^@^@^@^@^@<D1>`xW^N<93>ESC<91>
^@^@^@
^@^@^@^H^@^X^@^@^@^@^@^A^@^@^@<FF><81>^@^@^@^@test.txtUT^E^@^C^Z<F7>_eux^K^@^A^D<E8>^C^@^@^D<E8>^C^@^@PK^E^F^@^@^@^@^A^@^A^@N^@^@^@L^@^@^@^@^@
--------------------------f3dde3ddff901cd3--

这是使用 Playwright 实现等效 HTTP 请求的失败尝试:

from playwright.sync_api import sync_playwright

with sync_playwright() as playwright:
    browser = playwright.chromium.launch()
    context = browser.new_context()
    page = context.new_page()

    upload_file = "test.zip"
    with open(upload_file, "rb") as file:
        response = page.request.put(
            "http://localhost:8080",
            multipart={
                "name": "file",
                "filename": upload_file,
                "mimeType": "application/x-zip-compressed",
                "buffer": file.read(),
            }
        )

    print(response)

这会产生以下(明显错误的)HTTP 请求:

PUT / HTTP/1.1
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/115.0.5790.24 Safari/537.36
accept: */*
accept-encoding: gzip,deflate,br
content-type: multipart/form-data; boundary=----WebKitFormBoundarynU6IBe6rgn1KUgpw
content-length: 365
Host: localhost:8080
Connection: close

------WebKitFormBoundarynU6IBe6rgn1KUgpw
content-disposition: form-data; name="name"

file
------WebKitFormBoundarynU6IBe6rgn1KUgpw
content-disposition: form-data; name="filename"

test.zip
------WebKitFormBoundarynU6IBe6rgn1KUgpw
content-disposition: form-data; name="mimeType"

application/x-zip-compressed
------WebKitFormBoundarynU6IBe6rgn1KUgpw--

如何使用 Playwright 复制curl HTTP 请求?

python http multipartform-data put playwright-python
1个回答
0
投票

剧作家文档不是很清楚。

multipart
参数的结构应该是一个字典,每个表单部分都有一个键。在这种情况下,我们只提交一个“部分”,因此应该只有一个密钥。

将所需多部分表单提交的组件映射到 Playwright 多部分字典是有启发性的。例如下面的表单部分:

Content-Disposition: form-data; name="file"; filename="test.zip"
Content-Type: application/x-zip-compressed

映射到以下多部分字典:

multipart={
    "file": {                   # name="file"
        "name": "test.zip",     # filename="test.zip"
        "mimeType": "application/x-zip-compressed", # Content-Type value
        "buffer": file.read(),  # binary data from file
    }
}

所以完整的例子是:

from playwright.sync_api import sync_playwright

with sync_playwright() as playwright:
    browser = playwright.chromium.launch()
    context = browser.new_context()
    page = context.new_page()

    upload_file = "test.zip"
    with open(upload_file, "rb") as file:
        response = page.request.put(
            "http://localhost:8080",
            multipart={
                "file": {
                    "name": upload_file,
                    "mimeType": "application/x-zip-compressed",
                    "buffer": file.read(),
                }
            },
        )

    print(response)

产生以下 HTTP 请求:

PUT / HTTP/1.1
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/115.0.5790.24 Safari/537.36
accept: */*
accept-encoding: gzip,deflate,br
content-type: multipart/form-data; boundary=----WebKitFormBoundaryK3WyngXmdiXmbBHu
content-length: 376
Host: localhost:8080
Connection: close

------WebKitFormBoundaryK3WyngXmdiXmbBHu
content-disposition: form-data; name="file"; filename="test.zip"
content-type: application/x-zip-compressed

PK^C^D
^@^@^@^@^@<D1>`xW^N<93>ESC<91>
^@^@^@
^@^@^@^H^@^\^@test.txtUT        ^@^C^Z<F7>_e^Z<F7>_eux^K^@^A^D<E8>^C^@^@^D<E8>^C^@^@Test file
PK^A^B^^^C
^@^@^@^@^@<D1>`xW^N<93>ESC<91>
^@^@^@
^@^@^@^H^@^X^@^@^@^@^@^A^@^@^@<FF><81>^@^@^@^@test.txtUT^E^@^C^Z<F7>_eux^K^@^A^D<E8>^C^@^@^D<E8>^C^@^@PK^E^F^@^@^@^@^A^@^A^@N^@^@^@L^@^@^@^@^@
------WebKitFormBoundaryK3WyngXmdiXmbBHu--

请注意,这与curl 请求并不完全相同,但看起来足够接近。

© www.soinside.com 2019 - 2024. All rights reserved.