Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.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:HTTP发布一个带有流的大文件_Python_Http_Urllib2 - Fatal编程技术网

Python:HTTP发布一个带有流的大文件

Python:HTTP发布一个带有流的大文件,python,http,urllib2,Python,Http,Urllib2,我正在将可能较大的文件上载到web服务器。目前我正在这样做: import urllib2 f = open('somelargefile.zip','rb') request = urllib2.Request(url,f.read()) request.add_header("Content-Type", "application/zip") response = urllib2.urlopen(request) 但是,这会在发布之前将整个文件的内容读入内存。如何让它将文件流式传输到服务

我正在将可能较大的文件上载到web服务器。目前我正在这样做:

import urllib2

f = open('somelargefile.zip','rb')
request = urllib2.Request(url,f.read())
request.add_header("Content-Type", "application/zip")
response = urllib2.urlopen(request)
但是,这会在发布之前将整个文件的内容读入内存。如何让它将文件流式传输到服务器?

您尝试过吗

或者,如果您不想使用多部分/表单数据,请检查old post

它提出了两种选择:

  1. Use mmap, Memory Mapped file object
  2. Patch httplib.HTTPConnection.send

试试pycurl。我不知道安装程序会接受一个不在多部分/表单数据POST中的大文件,但这里有一个简单的示例,可以根据需要读取该文件

import os
import pycurl

class FileReader:
    def __init__(self, fp):
        self.fp = fp
    def read_callback(self, size):
        return self.fp.read(size)

c = pycurl.Curl()
c.setopt(pycurl.URL, url)
c.setopt(pycurl.UPLOAD, 1)
c.setopt(pycurl.READFUNCTION, FileReader(open(filename, 'rb')).read_callback)
filesize = os.path.getsize(filename)
c.setopt(pycurl.INFILESIZE, filesize)
c.perform()
c.close()

通过阅读systempuntoout链接的邮件列表线程,我找到了解决方案的线索

mmap
模块允许您打开类似字符串的文件。文件的一部分按需加载到内存中

下面是我现在使用的代码:

import urllib2
import mmap

# Open the file as a memory mapped string. Looks like a string, but 
# actually accesses the file behind the scenes. 
f = open('somelargefile.zip','rb')
mmapped_file_as_string = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)

# Do the request
request = urllib2.Request(url, mmapped_file_as_string)
request.add_header("Content-Type", "application/zip")
response = urllib2.urlopen(request)

#close everything
mmapped_file_as_string.close()
f.close()

文档没有说明您可以这样做,但是urllib2(和httplib)中的代码接受任何带有read()方法的对象作为数据。因此,使用打开的文件似乎可以做到这一点

您需要自己设置内容长度标题。如果未设置,urllib2将对数据调用len(),而文件对象不支持该数据

import os.path
import urllib2

data = open(filename, 'r')
headers = { 'Content-Length' : os.path.getsize(filename) }
response = urllib2.urlopen(url, data, headers)
这是处理您提供的数据的相关代码。它来自Python 2.7中
httplib.py
中的
HTTPConnection
类:

def send(self, data):
    """Send `data' to the server."""
    if self.sock is None:
        if self.auto_open:
            self.connect()
        else:
            raise NotConnected()

    if self.debuglevel > 0:
        print "send:", repr(data)
    blocksize = 8192
    if hasattr(data,'read') and not isinstance(data, array):
        if self.debuglevel > 0: print "sendIng a read()able"
        datablock = data.read(blocksize)
        while datablock:
            self.sock.sendall(datablock)
            datablock = data.read(blocksize)
    else:
        self.sock.sendall(data)

使用
请求
库可以执行以下操作

with open('massive-body', 'rb') as f:
    requests.post('http://some.url/streamed', data=f)

如前所述,下面是Python 2/Python 3的工作示例:

试试看:
从urllib2导入urlopen,请求
除:
从urllib.request导入urlopen,请求
headers={'Content length':str(os.path.getsize(filepath))}
将open(filepath,'rb')作为f:
请求(url,数据=f,标题=headers)
结果=urlopen(req).read().decode()

请求模块很棒,但有时您无法安装任何额外的模块…

我不想发送编码为“多部分/表单数据”的文件。这似乎可以做到这一点。我只是在找一篇原始文章。在Python2.7上,选项#2已经添加了补丁,块大小是8192,我想知道为什么。。嗯。这方面的标准是什么?谢谢JimB。我会用这个,除非我有几个人在Windows上用这个,我不想让他们安装任何其他东西。请确认下面的行是正确的:request=urllib2。request(url,mmapped_file_as_string)Related:Related:8K块大小仍然适用,如httplib.py,send()调用L#869。
urllib2.urlopen(url,数据,标题)
不将标题作为参数,因此
response=urllib2.urlopen(url,数据,标题)
行将不起作用。我在下面提供了工作代码
with open('massive-body', 'rb') as f:
    requests.post('http://some.url/streamed', data=f)