如何将curl命令转换为Python请求?

5cnsuln7  于 2023-03-06  发布在  Python
关注(0)|答案(3)|浏览(162)

在本Shopify教程之后,我尝试上传一张图片到Shopify。其中一个子任务是将curl命令转换为python请求。文件由用户上传,我使用request. FILES ['filename']将file变量传递给这个函数:

curl -v \
  -F "Content-Type=image/png" \
  -F "success_action_status=201" \
  -F "acl=private" \
  -F "key=tmp/45732462614/products/7156c27e-0331-4bd0-b758-f345afaa90d1/watches_comparison.png" \
  -F "x-goog-date=20221024T181157Z" \
  -F "x-goog-credential=merchant-assets@shopify-tiers.iam.gserviceaccount.com/20221024/auto/storage/goog4_request" \
  -F "x-goog-algorithm=GOOG4-RSA-SHA256" \
  -F "x-goog-signature=039cb87e2787029b56f498beb2deb3b9c34d96da642c1955f79225793f853760906abbd894933c5b434899d315da13956b1f67d8be54f470571d7ac1487621766a2697dfb8699c57d4e67a8b36ea993fde0f888b8d1c8bd3f33539d8583936bc13f9001ea3e6d401de6ad7ad2ae52d722073caf250340d5b0e92032d7ad9e0ec560848b55ec0f943595578a1d6cae53cd222d719acb363ba2c825e3506a52b545dec5be57074f8b1b0d58298a0b4311016752f4cdb955b89508376c38f8b2755fce2423acb3f592a6f240a21d8d2f51c5f740a61a40ca54769a736d73418253ecdf685e15cfaf7284e6e4d5a784a63d0569a9c0cffb660028f659e68a68fb80e" \
  -F "policy=eyJjb25kaXRpb25zIjpbeyJDb250ZW50LVR5cGUiOiJpbWFnZVwvcG5nIn0seyJzdWNjZXNzX2FjdGlvbl9zdGF0dXMiOiIyMDEifSx7ImFjbCI6InByaXZhdGUifSxbImNvbnRlbnQtbGVuZ3RoLXJhbmdlIiwxLDIwOTcxNTIwXSx7ImJ1Y2tldCI6InNob3BpZnktc3RhZ2VkLXVwbG9hZHMifSx7ImtleSI6InRtcFwvZ2NzXC80NTczMjQ2MjYxNFwvcHJvZHVjdHNcLzcxNTZjMjdlLTAzMzEtNGJkMC1iNzU4LWYzNDVhZmFhOTBkMVwvd2F0Y2hlc19jb21wYXJpc29uLnBuZyJ9LHsieC1nb29nLWRhdGUiOiIyMDIyMTAyNFQxODExNTdaIn0seyJ4LWdvb2ctY3JlZGVudGlhbCI6Im1lcmNoYW50LWFzc2V0c0BzaG9waWZ5LXRpZXJzLmlhbS5nc2VydmljZWFjY291bnQuY29tXC8yMDIyMTAyNFwvYXV0b1wvc3RvcmFnZVwvZ29vZzRfcmVxdWVzdCJ9LHsieC1nb29nLWFsZ29yaXRobSI6IkdPT0c0LVJTQS1TSEEyNTYifV0sImV4cGlyYXRpb24iOiIyMDIyLTEwLTI1VDE4OjExOjU3WiJ9" \
  -F "file=@/Users/shopifyemployee/Desktop/watches_comparison.png" \
   "https://shopify-staged-uploads.storage.googleapis.com/"

我使用chatgpt生成了以下python代码:

def uploadImage(stagedTarget, file):
    parameters = stagedTarget["parameters"]
    url = stagedTarget["url"]
    files = {
        'file': file,
    }
    data = {
        'Content-Type': parameters[0]['value'],
        'success_action_status': parameters[1]['value'],
        'acl': parameters[2]['value'],
        'key': parameters[3]['value'],
        'x-goog-date': parameters[4]['value'],
        'x-goog-credential': parameters[5]['value'],
        'x-goog-algorithm': parameters[6]['value'],
        'x-goog-signature': parameters[7]['value'],
        'policy': parameters[8]['value'],
    }
    print(f"{url = }, {data = }")
    response = requests.post(url, files=files, data=data)
    print(f"{response.status_code = }")
    print(f"{response.text = }")

    response = response.content
    response = json.loads(response)

服务器给出以下响应:

web_1      | response.status_code = 400
web_1      | response.text = "<?xml version='1.0' encoding='UTF-8'?><Error><Code>EntityTooSmall</Code><Message>Your proposed upload is smaller than the minimum object size specified in your Policy Document.</Message><Details>Content-length smaller than lower bound on range</Details></Error>"

我的文件大小只有46KB。我不知道为什么它太小了。我尝试了一个更大的文件,它仍然是一样的。我试图调用curl命令上传一个类似的本Map像文件,它是好的。我做错了什么?
更新:我尝试更新如下的python代码,它再次给我400错误:
一个三个三个一个

kr98yfug

kr98yfug1#

文件必须以二进制模式打开。我没有打开文件

def uploadImage(stagedTarget, file):
    # Get the permannent access_token
    parameters = stagedTarget["parameters"]
    url = stagedTarget["url"]
    files = {
        'Content-Type': parameters[0]['value'],
        'success_action_status': parameters[1]['value'],
        'acl': parameters[2]['value'],
        'key': parameters[3]['value'],
        'x-goog-date': parameters[4]['value'],
        'x-goog-credential': parameters[5]['value'],
        'x-goog-algorithm': parameters[6]['value'],
        'x-goog-signature': parameters[7]['value'],
        'policy': parameters[8]['value'],
        'file': file.open(mode='rb'),
    }
    response = requests.post(url, files=files)
    print(f"{response.status_code = }")
    print(f"{response.text = }")

    response = response.content
    response = json.loads(response)
x6h2sr28

x6h2sr282#

你需要传递一个打开的文件对象(可能是二进制模式),不要只传递文件名:将open(request.FILES['filename'], 'rb')作为第二个参数传递给uploadImage()
虽然在files输入中传递字符串时请求不会引发错误有点奇怪,但是我假设字符串只是请求的文件内容,尽管是非二进制模式,所以请求不会注意到差异。

u5rb5r59

u5rb5r593#

Note that the Content-Type header is included in the headers dictionary, and the file is passed in the files dictionary. The other parameters are included in the data dictionary. Finally, we use the requests.post method to send the HTTP request and return the response content.



import requests
    
    def uploadImage(stagedTarget, file):
        parameters = stagedTarget["parameters"]
        url = stagedTarget["url"]
        files = {
            'file': file,
        }
        headers = {
            'Content-Type': parameters[0]['value']
        }
        data = {
            'success_action_status': parameters[1]['value'],
            'acl': parameters[2]['value'],
            'key': parameters[3]['value'],
            'x-goog-date': parameters[4]['value'],
            'x-goog-credential': parameters[5]['value'],
            'x-goog-algorithm': parameters[6]['value'],
            'x-goog-signature': parameters[7]['value'],
            'policy': parameters[8]['value']
        }
        response = requests.post(url, headers=headers, data=data, files=files)
        return response.content

相关问题