+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-'''
-uploadform.py - A simple/minimalist yet flexible helper module to construct a POSTable mime
-message that is similar to a message generated by a browser when you submit an html form.
-Supports file uploads and even "incremental uploads" (by yielding) if you don't
-want to read the whole uploadable file into memory before POSTing it to the HTTP server.
-Provided "as is" - use it at your own risk and don't complain if it cuts down your limbs...
-Run this module to execute the test/example code.
-'''
-import uuid, urllib, urllib2
-
-__author__ = 'István Pásztor'
-__all__ = ['UploadForm']
-
-
-class UploadForm:
- def __init__(self, boundary=None):
- self.set_boundary(boundary)
- self.fields = []
-
- def set_boundary(self, boundary):
- self.boundary = urllib.quote(boundary) if boundary else '__--__{%s}__--__' % uuid.uuid4()
-
- def add_field(self, name, value, **params):
- # see _Field.__init__() for the description of the parameters.
- field = _Field(name, value, **params)
- self.fields.append(field)
- return field
-
- def get_request_headers(self, calculate_content_length=True):
- assert self.fields
- headers = {'Content-Type': 'multipart/form-data; boundary='+self.boundary}
- if not calculate_content_length:
- return headers
- content_length = self.get_size()
- headers['Content-Length'] = str(content_length)
- return (headers, content_length)
-
- def __iter__(self):
- assert self.fields
- boundary = '--' + self.boundary + '\r\n'
- for field in self.fields:
- yield boundary
- for chunk in field:
- yield chunk
- yield '--'
- yield self.boundary
- yield '--\r\n'
-
- def __str__(self):
- return ''.join(s for s in self)
-
- def dump(self, f):
- for chunk in self:
- f.write(chunk)
-
- def get_size(self):
- return (2+len(self.boundary)+2) * (len(self.fields)+1) + 2 + sum(field.get_size() for field in self.fields)
-
-
-class PingForm:
- def __init__(self, boundary=None):
- self.set_boundary(boundary)
- self.fields = []
-
- def set_boundary(self, boundary):
- self.boundary = urllib.quote(boundary) if boundary else '__--__{%s}__--__' % uuid.uuid4()
-
- def add_field(self, name, value, **params):
- # see _Field.__init__() for the description of the parameters.
- field = _Field(name, value, **params)
- self.fields.append(field)
- return field
-
- def get_request_headers(self):
- assert self.fields
- headers = {'Content-Type': 'multipart/form-data; boundary='+self.boundary}
- return (headers)
-
- def __iter__(self):
- assert self.fields
- boundary = '--' + self.boundary + '\r\n'
- for field in self.fields:
- yield boundary
- for chunk in field:
- yield chunk
- yield '--'
- yield self.boundary
- yield '--\r\n'
-
- def __str__(self):
- return ''.join(s for s in self)
-
- def dump(self, f):
- for chunk in self:
- f.write(chunk)
-
- def get_size(self):
- return (2+len(self.boundary)+2) * (len(self.fields)+1) + 2 + sum(field.get_size() for field in self.fields)
-
-
-class _Header:
- def __init__(self, _header_name, _header_value, **params):
- self.name = _header_name
- self.value = _header_value
- self.params = params
-
- def __iter__(self):
- yield _stringify(self.name)
- yield ': '
- yield _stringify(self.value)
- for name, value in self.params.iteritems():
- yield '; '
- yield _stringify(name)
- yield '="'
- yield _stringify(value).replace('\\', '\\\\').replace('"', '\\"')
- yield '"'
- yield '\r\n'
-
- def get_size(self):
- def _param_size(name, value):
- value = _stringify(value)
- return 5 + len(_stringify(name)) + len(value) + value.count('\\') + value.count('"')
- return 4 + len(_stringify(self.name)) + len(_stringify(self.value)) + sum(_param_size(name, value) for name, value in self.params.iteritems())
-
-
-class _Field:
- BUFSIZE = 16*1024 # BUFSIZE used when yielding data from file objects
-
- def __init__(self, name, value, **params):
- '''
- @param params: Contains additional key-value pairs besides the "name" parameter for the Content-Disposition
- header. Example: filename='x.zip'
- @param value: This parameter can be a string, a unicode object, or a (file-object, size) tuple. In case of
- unicode object the string is converted to utf-8 before converting to mime. In case of a file-object we read
- the data starting from the current file pointer.
- '''
- params['name'] = name
- self.headers = [_Header('Content-Disposition', 'form-data', **params)]
- assert isinstance(value, (str, unicode, tuple))
- self.value = value
-
- def add_header(self, name, value, **params):
- '''
- You can add additional mime headers, for example a "Content-Type" header with "text/plain" value with optional
- parameters like charset="UTF-8"
- '''
- self.headers.append(_Header(name, value, **params))
-
- def __iter__(self):
- for header in self.headers:
- for chunk in header:
- yield chunk
- yield '\r\n'
-
- if isinstance(self.value, str):
- yield self.value
- elif isinstance(self.value, unicode):
- yield self.value.encode('utf-8')
- else:
- bytes_left = self.value[1]
- while bytes_left > 0:
- bytes_to_read = min(self.BUFSIZE, bytes_left)
- data = self.value[0].read(bytes_to_read)
- if not data:
- raise Exception('The specified file object doesn\'t contain enough data!')
- yield data
- bytes_left -= len(data)
- yield '\r\n'
-
- def __str__(self):
- return ''.join(s for s in self)
-
- def get_size(self):
- size = sum(header.get_size() for header in self.headers) + 2
-
- if isinstance(self.value, str):
- size += len(self.value)
- elif isinstance(self.value, unicode):
- size += len(self.value.encode('utf-8'))
- else:
- size += self.value[1]
-
- size += 2 # newline
- return size
-
-
-def _stringify(s):
- return s.encode('utf-8') if isinstance(s, unicode) else s
-
-if __name__ == '__main__':
- # SIMPLE REQUETE EN GET
- '''
- Test/example code.
- print 'BOUH !'
- url = 'http://allo_serveur/?action=get_instances'
- opener = urllib2.build_opener()
- response = opener.open(url).read()
- print response
- '''
-
- # TEST UPLOAD AVEC REQUESTS (pip install requests)
- import requests
- url = 'http://allo_serveur/?action=upload_info'
- # files = {'file': open('test.json', 'rb')}
- with open("test.json", "r") as myfile:
- data = myfile.read()
- # r = requests.post(url, files=files)
- r = requests.post(url, data=data)
- print r.text
-
- # TEST UPLOAD AVEC URLLIB2 (PUT REFUSE)
- '''
- import json
- #import urllib2
- url = 'http://allo_serveur/?action=upload_info'
- with open("test.json", "r") as myfile:
- data = myfile.read()
- postdata = urllib.urlencode(data)
- req = urllib2.Request(url, postdata, {'Content-Type': 'application/json'})
- f = urllib2.urlopen(req)
- response = f.read()
- f.close()
- '''
-
- # TEST UPLOAD AVEC URLLIB (PUT REFUSE)
- '''
- import os
- filename = 'test.json'
- # AJOUT DU PATH USELESS ?
- #filepath = os.path.join('j:\\', filename)
- with open(filename, 'rb') as f:
- form = UploadForm()
- # Adding a field by setting its value by reading from file like object...
- form.add_field('file', (f, os.path.getsize(filename)), filename=filename)
- #field = form.add_field('file_from_mem', u'This is the content of Pistike\'s text file.\n', filename='memfile.txt')
- # Adding headers is optional but we do it this time just to demonstrate it...
- #field.add_header('Content-Type', 'text/plain', charset='UTF-8')
- #field.add_header('MyHeader', 'my_header_value', quote_test_param='m\\y"param"2')
- # simulating a type="text" input field on the form with name="comment"
- #form.add_field('comment', u'Árvíztűrő tükörfúrógép')
- # simulating a type="checkbox" input field on the form with name="my_checkbox"
- #form.add_field('my_checkbox', 'on')
- headers, content_length = form.get_request_headers()
- content = str(form)
-
- print 'Headers: %s' % (headers,)
- print 'Content-Length: %s' % len(content)
- print content
-
- assert len(content) == content_length
-
- import httplib
-
- conn = httplib.HTTPConnection('allo_serveur')
- try:
- conn.request('POST', '/?action=upload_info', content, headers=headers)
- resp = conn.getresponse()
- print resp.status
- print resp.read()
- finally:
- conn.close()
- '''
\ No newline at end of file