Welcome, guest | Sign In | My Account | Store | Cart

Usage:

#!/usr/bin/env python2.5
#
# html file:
#    <form action="test.cgi" method="POST" enctype="multipart/form-data">
#    <input name="file1" type="file"><input type="submit"></form>

# test.cgi: ...

import SingleUpload

def upload():
   fr = SingleUpload.open()
   fw = open('/tmp/%s' %fr.filename, 'wb')

   while True:
      l = fr.read(65536)
      if not l:
         break

      fw.write(l)
      fw.flush()
   fw.close()

print 'Content-Type: text/plain\r\n\r\n'
try:
   upload()
   print 'OK'
except IOError:
   __import__('traceback').print_exc(
      file=__import__('sys').stdout )
Python, 105 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
# SingleUpload.py
from sys import stdin
from re import compile
from cgi import parse_header
from os import environ as env

search = compile(r'([^\\/]+)$').search

def open():
	global next, last
	try:
		next = '--' + parse_header(env['CONTENT_TYPE'])[1]['boundary']
	except:
		raise IOError

	last = next + '--'

	filename = None
	while not filename:
		while True:
			l = stdin.readline(65536)
			if not l:
				raise IOError

			if l[:2] == '--':
				sl = l.strip()
				if sl == next:
					break
				if sl == last:
					raise IOError

		for i in xrange(10):
			l = stdin.readline(65536).strip()
			if not l:
				break
			try:
				filename = parse_header(l.split(':', 1)[1])[1]['filename']
				break
			except:
				continue

	m = search(filename)
	if not m:
		raise IOError
	filename = m.groups()[0]

	while stdin.readline(65536).strip():
		pass

	def _readline():
		el = ''
		while True:
			l = stdin.readline(65536)
			if not l:
				raise IOError

			if l[:2] == '--' and el:
				sl = l.strip()
				if sl == next or sl == last:
					break

			ol, el = el, l[-2:] == '\r\n' and '\r\n' or (
				l[-1] == '\n' and '\n' or '')

			p = len(el)
			if p == 0:
				yield ol + l
			else:
				yield ol + l[:-p]
		while True:
			yield None

	rl = _readline().next
	def _next(size=65536):
		buff = _next.buff
		while len(buff) < size:
			l = rl()
			if not l:
				_next.buff = ''
				return buff

			buff += l

		r, _next.buff = buff[:size], buff[size:]
		return r

	_next.buff = rl()

	def _read(size=None):
		if size:
			return _next(size)

		fp = __import__('StringIO').StringIO()
		while True:
			l = _next()
			if not l:
				return fp.getvalue()

			fp.write(l)

	fp = type('SingleFile', (), {})()
	fp.next = _next; fp.read = _read
	fp.filename = filename

	return fp

1 comment

Matthew Street 16 years, 4 months ago  # | flag

Thank you. I sat in on a PHP introduction and became even more interested in CGI, but not entirely sold on PHP. Since I already know and love basic python, I've started learning to do cgi with python instead.

An upload script in PHP is one of the things I thought were fun and I'm really glad I found a simple python example. I made an account here just so I could say thanks.