Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Python请求发布二进制(视频)文件_Python_Python Requests - Fatal编程技术网

使用Python请求发布二进制(视频)文件

使用Python请求发布二进制(视频)文件,python,python-requests,Python,Python Requests,我有一段PHP代码,可以将二进制文件上传到我没有shell访问权限的远程服务器。PHP代码是: 函数上传($uri,$filename){ $ch=curl_init(); curl_setopt($ch,CURLOPT_URL,$uri); curl_setopt($ch,CURLOPT_POST,true); curl_setopt($ch,CURLOPT_POSTFIELDS,array('file'=>@'.$filename)); curl_exec($ch); 卷曲关闭($ch);

我有一段PHP代码,可以将二进制文件上传到我没有shell访问权限的远程服务器。PHP代码是:

函数上传($uri,$filename){
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$uri);
curl_setopt($ch,CURLOPT_POST,true);
curl_setopt($ch,CURLOPT_POSTFIELDS,array('file'=>@'.$filename));
curl_exec($ch);
卷曲关闭($ch);
}
这会产生如下标题:

HTTP/1.1
Host: XXXXXXXXX
Accept: */*
Content-Length: 208045596
Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------360aaccde050
我试图使用请求将其移植到python,但无法让服务器接受我的帖子。我已经尝试了使用requests.post的各种方法,但是标题不会模仿上面的方法

这将成功地将二进制文件传输到服务器(可以通过观察wireshark来判断),但由于标头不是服务器所期望的,因此会被拒绝。但响应代码是200

files = {'bulk_test2.mov': ('bulk_test2.mov', open('bulk_test2.mov', 'rb'))}
response = requests.post(url, files=files)
“请求”代码生成的标题为:

HTTP/1.1
Host: XXXX
Content-Length: 160
Content-Type: multipart/form-data; boundary=250852d250b24399977f365f35c4e060
Accept-Encoding: gzip, deflate, compress
Accept: */*
User-Agent: python-requests/2.2.1 CPython/2.7.5 Darwin/13.1.0

--250852d250b24399977f365f35c4e060
Content-Disposition: form-data; name="bulk_test2.mov"; filename="bulk_test2.mov"


--250852d250b24399977f365f35c4e060--

关于如何使请求与PHP代码生成的头匹配,您有什么想法吗?

有两大区别:

  • PHP代码发布一个名为
    file
    的字段,Python代码发布一个名为
    bulk_test2.mov
    的字段

  • Python代码发布一个空文件。其中内容长度标头为160字节,正好是多部分边界和
    内容处置
    部分标头占用的空间量。
    bulk_test2.mov
    文件确实是空的,或者您多次尝试在不回放或重新打开文件对象的情况下发布文件

  • 要解决第一个问题,请使用
    'file'
    作为
    文件
    字典中的键:

    files = {'file': open('bulk_test2.mov', 'rb')}
    response = requests.post(url, files=files)
    
    我只使用openfile对象作为值<在这种情况下,代码>请求将直接从文件对象获取文件名

    第二个问题只有你能解决。重复发布时,请确保不要重复使用
    文件。重新打开,或使用
    files['file'].seek(0)
    将读取位置倒回起始位置

    Expect:100 continue
    头是一个可选的客户端功能,要求服务器:;它不是必需的标题,任何未能发布文件对象的情况都不会是由于
    请求
    是否使用此功能造成的。如果您不使用此功能,HTTP服务器就会出现异常行为,这违反了HTTP RFCs,您将面临更大的问题。这肯定不是
    请求
    可以为您解决的问题

    如果您确实设法发布实际的文件数据,那么
    内容长度的任何微小变化都是由于Python和PHP之间的(随机)边界长度不同造成的。这是正常的,而不是上传问题的原因,除非您的目标服务器严重损坏。再说一次,不要试图用Python修复这种中断

    然而,我想你忽略了更简单的事情。例如,服务器可能会将某些
    用户代理
    头列入黑名单。您可以使用以下命令清除某些默认标题
    请求
    集:

    看看这是否有区别

    如果服务器由于无法处理请求而无法处理您的请求,您可以尝试将会话用作上下文管理器,以确保关闭所有会话连接:

    files = {'file': open('bulk_test2.mov', 'rb')}
    with requests.Session() as session:
        response = session.post(url, files=files, stream=True)
    
    你可以加上:

    response.raw.close()
    

    用于良好测量。

    被拒绝,响应代码为200?可能返回了一个错误消息页?我注意到您的
    内容长度只有160字节。。这正是多部分边界和元数据加上换行符的大小。您的文件似乎是空的。因此,如果我使用`res=requests.post(url,data=open_file,headers={'Content-Type':'multipart/form data;boundary=------------------------------------360aaccde050'}),我会得到
    内容长度:208045390
    ,这是准确的。但是头与服务器期望的又不同,因此上面创建了类似头的内容长度:208045540 Content Type:multipart/form data;boundary=bd19b64db83e4ebbaadc4835f9727856接受编码:gzip、deflate、compress-Accept:/User-Agent:python-requests/2.2.1 CPython/2.7.5 Darwin/13.1.0--bd19b64db83e4ebbaadc4835f9727856内容处理:表单数据;name=“file”;filename=“bulk_test2.mov”这与我需要的内容不同(如下所示)内容长度:208045596预期:100继续内容类型:多部分/fo…不要过于关注精确的标题
    Expect:100 continue
    不是必需的标题,唯一要做的就是暂停上传正文,直到服务器说可以上传正文。如果您的HTTP上载失败,因为该头文件丢失,那么您的服务器将面临比这篇文章更大的问题。而16字节内容长度的差异完全是由PHP和Python之间(正确生成的)多部分边界相差8个字符这一事实来解释的。这永远不会是问题的原因。我如此关注标题的唯一原因是,在文章完成后,目的地似乎依赖于它们的代码逻辑。如果我的头与PHP生成的头不相同,服务器将不会处理该文件。@user3524641:然后在会话中将
    keep_alive
    设置为
    False
    response.raw.close()