将curl请求转换为python代码时请求错误

2024-09-25 00:25:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试将以下curl请求转换为python@3.8密码curl将excel文件数据发送到服务器

curl请求被正确解析,但是我的python代码不起作用,我从服务器收到了一个错误的请求

curl -X POST "http://localhost:8080/rest/2.0/import/ejob" -H "accept: application/json" -H "Authorization: Basic xyz" -H "Content-Type: multipart/form-data" -F "deleteFile=" -F "simulation=" -F "fileName=import_file" -F "sheetName=" -F "headerRow=" -F "sendNotification=" -F "sheetIndex=" -F "fileId=" -F 'template= [ { "resourceType": "xyz", "type": { "name": "xyz" }, "identifier": { "name": "${1}", "domain": { "name": "xyz", "community": { "name": "test" } } } } ]' -F "batchSize=10000" -F "file=@filename.xlsx;type=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"

Python代码:

url = "http://localhost:8080/rest/2.0/import/ejob"

payload={'deleteFile': '',
'simulation': '',
'fileName': 'xyz',
'sheetName': '',
'headerRow': '',
'sendNotification': '',
'sheetIndex': '',
'fileId': '',
'template': ' [ { "resourceType": "Asset", "type": { "name": "xyz" }, "identifier": { "name": "${1}", "domain": { "name": "xyz", "community": { "name": "file" } } } } ]',
'batchSize': '10000',
'file': '@filename.xlsx;type=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}
files = {'file': ('import_file', open('filename.xlsx', 'rb'), 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', {'Expires': '0'})}

headers = {
  'accept': 'application/json',
  'Authorization': 'Basic xyz',
  'Content-Type': 'multipart/form-data',
}

response = requests.request("POST", url, headers=headers, data=payload, files=files)

print(response.text)

Error as seen from wireshark for python code

对于从python发送的请求,在Wireshark中看不到边界。下面的屏幕截图是针对CURL的

I don't see boundary in my python request


Tags: nameimportdataapplicationtypecurlfilenamexlsx
3条回答

问题在于在标头中传递“内容类型”:“多部分/表单数据”。我从有效负载中删除了该文件,并修改了头文件以修复该问题

试试这个:

import requests

headers = {
    'accept': 'application/json',
    'Authorization': 'Basic xyz',
    'Content-Type': 'multipart/form-data',
}

files = {
    'deleteFile': (None, ''),
    'simulation': (None, ''),
    'fileName': (None, 'import_file'),
    'sheetName': (None, ''),
    'headerRow': (None, ''),
    'sendNotification': (None, ''),
    'sheetIndex': (None, ''),
    'fileId': (None, ''),
    'template': (None, ' [ { "resourceType": "xyz", "type": { "name": "xyz" }, "identifier": { "name": "${1}", "domain": { "name": "xyz", "community": { "name": "test" } } } } ]'),
    'batchSize': (None, '10000'),
    'file': ('filename.xlsx;type', open('filename.xlsx;type', 'rb')),
}

response = requests.post('http://localhost:8080/rest/2.0/import/ejob', headers=headers, files=files)
 

在不知道将请求发送到哪个服务器的情况下很难确定,但我猜您的问题是在datafiles参数中复制了file表单字段

当您在传递给datafiles参数的dict中使用相同的键时,请求将对请求使用多部分编码,并使用来自这两个dict的数据

例如,当我在系统上尝试以下代码时:

requests.post("http://localhost:8000", data={"file": "foo"}, files={"file": "bar"})

它转换为以下HTTP请求:

POST / HTTP/1.1
Host: localhost:8000
User-Agent: python-requests/2.24.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Length: 231
Content-Type: multipart/form-data; boundary=2756042e934999f01bd91212ac4ae994

 2756042e934999f01bd91212ac4ae994
Content-Disposition: form-data; name="file"

foo
 2756042e934999f01bd91212ac4ae994
Content-Disposition: form-data; name="file"; filename="file"

bar
 2756042e934999f01bd91212ac4ae994-

在您的情况下,可能是服务器在HTTP请求中看到了第一个file表单字段,发现它没有filename属性,并决定拒绝格式错误的请求

相反,请尝试从payload字典中删除file键,以便在生成的HTTP请求中只有一个file表单字段

import requests

url = "http://localhost:8080/rest/2.0/import/ejob"
payload = {
    "deleteFile": "",
    "simulation": "",
    "fileName": "xyz",
    "sheetName": "",
    "headerRow": "",
    "sendNotification": "",
    "sheetIndex": "",
    "fileId": "",
    "template": ' [ { "resourceType": "Asset", "type": { "name": "xyz" }, "identifier": { "name": "${1}", "domain": { "name": "xyz", "community": { "name": "file" } } } } ]',
    "batchSize": "10000",
}
files = {
    "file": (
        "import_file",
        open("filename.xlsx", "rb"),
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        {"Expires": "0"},
    )
}
headers = {
    "accept": "application/json",
    "Authorization": "Basic xyz",
    "Content-Type": "multipart/form-data",
}

response = requests.post(url, headers=headers, data=payload, files=files)

顺便说一句,部分问题是您在Python payloaddict的file键中使用了@filename.xlsx,但是@是一种特殊的curl语法,它在请求中包含指定文件的内容

curl man page开始:

-F, form <name=content>

(HTTP SMTP IMAP) For HTTP protocol family, this lets curl emulate a filled-in form in which a user has pressed the submit button. This causes curl to POST data using the Content-Type multipart/form-data according to RFC 2388.

For SMTP and IMAP protocols, this is the mean to compose a multipart mail message to transmit.

This enables uploading of binary files etc. To force the 'content' part to be a file, prefix the file name with an @ sign. To just get the content part from a file, prefix the file name with the symbol <. The difference between @ and < is then that @ makes a file get attached in the post as a file upload, while the < makes a text field and just get the contents for that text field from a file.

在请求库中,@没有这种效果;相反,它只是作为普通字符插入到请求中

相关问题 更多 >