Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.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脚本使用POST发送文件_Python_Post_File Upload_Http Post - Fatal编程技术网

从Python脚本使用POST发送文件

从Python脚本使用POST发送文件,python,post,file-upload,http-post,Python,Post,File Upload,Http Post,有没有从Python脚本使用POST发送文件的方法?有。您将使用urlib2模块,并使用multipart/formdata内容类型进行编码。下面是一些示例代码,可以帮助您入门——这不仅仅是文件上传,但您应该能够通读并了解它的工作原理: user_agent = "image uploader" default_message = "Image $current of $total" import logging import os from os.path import abspath, i

有没有从Python脚本使用POST发送文件的方法?

有。您将使用
urlib2
模块,并使用
multipart/formdata
内容类型进行编码。下面是一些示例代码,可以帮助您入门——这不仅仅是文件上传,但您应该能够通读并了解它的工作原理:

user_agent = "image uploader"
default_message = "Image $current of $total"

import logging
import os
from os.path import abspath, isabs, isdir, isfile, join
import random
import string
import sys
import mimetypes
import urllib2
import httplib
import time
import re

def random_string (length):
    return ''.join (random.choice (string.letters) for ii in range (length + 1))

def encode_multipart_data (data, files):
    boundary = random_string (30)

    def get_content_type (filename):
        return mimetypes.guess_type (filename)[0] or 'application/octet-stream'

    def encode_field (field_name):
        return ('--' + boundary,
                'Content-Disposition: form-data; name="%s"' % field_name,
                '', str (data [field_name]))

    def encode_file (field_name):
        filename = files [field_name]
        return ('--' + boundary,
                'Content-Disposition: form-data; name="%s"; filename="%s"' % (field_name, filename),
                'Content-Type: %s' % get_content_type(filename),
                '', open (filename, 'rb').read ())

    lines = []
    for name in data:
        lines.extend (encode_field (name))
    for name in files:
        lines.extend (encode_file (name))
    lines.extend (('--%s--' % boundary, ''))
    body = '\r\n'.join (lines)

    headers = {'content-type': 'multipart/form-data; boundary=' + boundary,
               'content-length': str (len (body))}

    return body, headers

def send_post (url, data, files):
    req = urllib2.Request (url)
    connection = httplib.HTTPConnection (req.get_host ())
    connection.request ('POST', req.get_selector (),
                        *encode_multipart_data (data, files))
    response = connection.getresponse ()
    logging.debug ('response = %s', response.read ())
    logging.debug ('Code: %s %s', response.status, response.reason)

def make_upload_file (server, thread, delay = 15, message = None,
                      username = None, email = None, password = None):

    delay = max (int (delay or '0'), 15)

    def upload_file (path, current, total):
        assert isabs (path)
        assert isfile (path)

        logging.debug ('Uploading %r to %r', path, server)
        message_template = string.Template (message or default_message)

        data = {'MAX_FILE_SIZE': '3145728',
                'sub': '',
                'mode': 'regist',
                'com': message_template.safe_substitute (current = current, total = total),
                'resto': thread,
                'name': username or '',
                'email': email or '',
                'pwd': password or random_string (20),}
        files = {'upfile': path}

        send_post (server, data, files)

        logging.info ('Uploaded %r', path)
        rand_delay = random.randint (delay, delay + 5)
        logging.debug ('Sleeping for %.2f seconds------------------------------\n\n', rand_delay)
        time.sleep (rand_delay)

    return upload_file

def upload_directory (path, upload_file):
    assert isabs (path)
    assert isdir (path)

    matching_filenames = []
    file_matcher = re.compile (r'\.(?:jpe?g|gif|png)$', re.IGNORECASE)

    for dirpath, dirnames, filenames in os.walk (path):
        for name in filenames:
            file_path = join (dirpath, name)
            logging.debug ('Testing file_path %r', file_path)
            if file_matcher.search (file_path):
                matching_filenames.append (file_path)
            else:
                logging.info ('Ignoring non-image file %r', path)

    total_count = len (matching_filenames)
    for index, file_path in enumerate (matching_filenames):
        upload_file (file_path, index + 1, total_count)

def run_upload (options, paths):
    upload_file = make_upload_file (**options)

    for arg in paths:
        path = abspath (arg)
        if isdir (path):
            upload_directory (path, upload_file)
        elif isfile (path):
            upload_file (path)
        else:
            logging.error ('No such path: %r' % path)

    logging.info ('Done!')

您可能还想看一看。我发现使用httplib2比使用内置HTTP模块更简洁。

Chris Atley的库在这方面做得非常好(特别是方便的函数
poster.encode.multipart\u encode()
)。作为奖励,它支持大文件流,而无需将整个文件加载到内存中。另请参见。

阻止您直接在文件对象上使用urlopen的唯一原因是,内置文件对象缺少len定义。一种简单的方法是创建一个子类,它为urlopen提供正确的文件。 我还修改了下面文件中的内容类型标题

import os
import urllib2
class EnhancedFile(file):
    def __init__(self, *args, **keyws):
        file.__init__(self, *args, **keyws)

    def __len__(self):
        return int(os.fstat(self.fileno())[6])

theFile = EnhancedFile('a.xml', 'r')
theUrl = "http://example.com/abcde"
theHeaders= {'Content-Type': 'text/xml'}

theRequest = urllib2.Request(theUrl, theFile, theHeaders)

response = urllib2.urlopen(theRequest)

theFile.close()


for line in response:
    print line
发件人:

请求使上载多部分编码文件变得非常简单:

with open('report.xls', 'rb') as f:
    r = requests.post('http://httpbin.org/post', files={'report.xls': f})
就这样。我不是开玩笑-这是一行代码。文件已发送。让我们检查一下:

>>> r.text
{
  "origin": "179.13.100.4",
  "files": {
    "report.xls": "<censored...binary...data>"
  },
  "form": {},
  "url": "http://httpbin.org/post",
  "args": {},
  "headers": {
    "Content-Length": "3196",
    "Accept-Encoding": "identity, deflate, compress, gzip",
    "Accept": "*/*",
    "User-Agent": "python-requests/0.8.0",
    "Host": "httpbin.org:80",
    "Content-Type": "multipart/form-data; boundary=127.0.0.1.502.21746.1321131593.786.1"
  },
  "data": ""
}
>>r.text
{
“来源”:“179.13.100.4”,
“文件”:{
“report.xls”:”
},
“形式”:{},
“url”:”http://httpbin.org/post",
“args”:{},
“标题”:{
“内容长度”:“3196”,
“接受编码”:“标识、泄气、压缩、gzip”,
“接受”:“*/*”,
“用户代理”:“python请求/0.8.0”,
“主机”:“httpbin.org:80”,
“内容类型”:“多部分/表单数据;边界=127.0.0.1.502.21746.1321131593.786.1”
},
“数据”:”
}

看起来python请求无法处理非常大的多部分文件

文档建议您查看
请求工具带


从他们的文档中。

我正在尝试测试django rest api及其对我的作用:

def visit_v2(device_code, camera_code):
    image1 = MultipartParam.from_file("files", "/home/yuzx/1.txt")
    image2 = MultipartParam.from_file("files", "/home/yuzx/2.txt")
    datagen, headers = multipart_encode([('device_code', device_code), ('position', 3), ('person_data', person_data), image1, image2])
    print "".join(datagen)
    if server_port == 80:
        port_str = ""
    else:
        port_str = ":%s" % (server_port,)
    url_str = "http://" + server_ip + port_str + "/adopen/device/visit_v2"
    headers['nothing'] = 'nothing'
    request = urllib2.Request(url_str, datagen, headers)
    try:
        response = urllib2.urlopen(request)
        resp = response.read()
        print "http_status =", response.code
        result = json.loads(resp)
        print resp
        return result
    except urllib2.HTTPError, e:
        print "http_status =", e.code
        print e.read()
def test_upload_file(self):
        filename = "/Users/Ranvijay/tests/test_price_matrix.csv"
        data = {'file': open(filename, 'rb')}
        client = APIClient()
        # client.credentials(HTTP_AUTHORIZATION='Token ' + token.key)
        response = client.post(reverse('price-matrix-csv'), data, format='multipart')

        print response
        self.assertEqual(response.status_code, status.HTTP_200_OK)

pip安装http\u文件

#
导入urllib3
urllib3.disable_警告(urllib3.exceptions.UnsecureRequestWarning)
导入请求
#ццццццццhttpцu文件
从http\u文件导入下载\u文件
#создание новой сессии
s=请求。会话()
#соеденение с сервером через созданную сессию
s、 获取('URL\u MAIN',verify=False)
#ззззззззззззззазззаззз
下载_文件('local_filename','fileUrl',s)

在python 2.6.6上,我在Windows上使用此代码时,在多部分边界解析中遇到错误。我必须从string.letters更改为string.ascii_字母,正如在上讨论的那样,这样才能工作。这里讨论了对边界的要求:调用run_upload({'server':'','thread':'',paths=['/path/to/file.txt'])会导致此行出错:upload_file(path),因为“upload file”需要3个参数,所以我将其替换为此行upload_file(path,1,1)没有示例说明如何处理文件上载。链接已过时+没有内联示例。它已移至。另一方面,现在我可能会推荐
请求
。@robert我用Python2.7测试你的代码,但它不起作用。urlopen(请求(URL,theFile,…)只是将文件的内容编码为一篇普通的文章,但不能指定正确的表单字段。我甚至尝试了变体urlopen(URL,urlencode({'serverside_field_name':EnhancedFile('my_file.txt'))),它上载了一个文件,但(当然!)的内容不正确。我错过什么了吗?谢谢你的回答。通过使用上面的代码,我已经使用PUT请求将2.2GB的原始图像文件传输到Web服务器中。我也在尝试同样的事情&如果文件大小小于~1.5MB,它的工作就很好。否则就是抛出一个错误。。请看。我试图做的是登录到一些网站使用的要求,我已经成功地做到了,但现在我想上传一个视频后,登录和形式有一个不同的字段填写之前提交。那么,我应该如何传递这些值,如videos description、videos title等,您可能希望将open('report.xls','rb')作为f:r=requests.post('http://httpbin.org/post,files={report.xls':f}),因此,它会在打开文件后再次关闭该文件。这个答案应该更新,以包括Hjulle关于使用上下文管理器确保文件关闭的建议。这对我不起作用,它说“405方法不允许”。将open(file_path,'rb')作为f:response=requests.post(url=url,data=f,auth=HTTPBasicAuth)(username=id,password=password))此代码导致内存泄漏-您忘记了关闭文件。。