submitting a jpeg to a web site?

S

Steven D.Arnold

Hi,

I am curious how one might submit a JPEG to a web site using Python.
I've tried urllib.urlopen, passing a dictionary that contained a key
pointing to a string that contains the bytes of the JPEG, but that
didn't apparently work. I did use the urllib.urlencode function on the
dict before calling urlopen. It seems on the face of it that urlopen
is not the ordained way to do what I want here.

The <form> tag of the page I'm submitting to looks like this:

<form action="application_one_process.php" name="mainForm"
method="POST" enctype="multipart/form-data" accept-charset="US-ASCII">

The enctype seems to suggest I need some kind of MIME-like capability
to do this right. Does anyone know what I should be doing to make this
work?

Thanks in advance,
steve
 
G

Georgy Pruss

| Hi,
|
| I am curious how one might submit a JPEG to a web site using Python.
| I've tried urllib.urlopen, passing a dictionary that contained a key
| pointing to a string that contains the bytes of the JPEG, but that
| didn't apparently work. I did use the urllib.urlencode function on the
| dict before calling urlopen. It seems on the face of it that urlopen
| is not the ordained way to do what I want here.
|
| The <form> tag of the page I'm submitting to looks like this:
|
| <form action="application_one_process.php" name="mainForm"
| method="POST" enctype="multipart/form-data" accept-charset="US-ASCII">
|
| The enctype seems to suggest I need some kind of MIME-like capability
| to do this right. Does anyone know what I should be doing to make this
| work?
|
| Thanks in advance,
| steve
|


It's not a "product version", but it works at my site (Windows XP,
Apache/2.0.47 (Win32) PHP/4.3.3 mod_python/3.1.2b Python/2.3.2)
If you have Unix, you can get rid of all msvcrt stuff.

# test_upload.py
# upload form/script

# 1st parameter - (this) script name
# 2nd parameter - file field name
the_form = """
<FORM METHOD="POST" ACTION="%s" enctype="multipart/form-data">
<INPUT TYPE=FILE NAME="%s" size=50>
<INPUT TYPE="SUBMIT" VALUE="Upload">
</FORM>
"""


try:
import msvcrt,os
msvcrt.setmode( 0, os.O_BINARY ) # stdin = 0
msvcrt.setmode( 1, os.O_BINARY ) # stdout = 1
except ImportError:
pass


print "Content type: text/html"
print

import sys, os, traceback, re
import cgi
import cgitb; cgitb.enable()


def strip_path( fpname ):
"""strip off leading path and drive stuff from dos/unix/mac file full name
takes care of '/' ':' '\' '%2f' '%5c' '%3a'
"""
fname = re.sub( r"(%(2f|2F|5c|5C|3a|3A))|/|\\|:", '/', fpname )
delim = fname.rfind( '/' ) # -1 for not found, will return full fname
return fname[delim+1:]


def check_ext( file_name, ext_set ):
ext = file_name.rfind('.')
if ext < 0:
return False
ext = file_name[ext+1:].lower()
# was re.match( '^(gif)|(jpg)|(zip)$', ext, re.I )
exts = ext_set.lower().split(',')
for good_ext in exts:
if ext == good_ext:
return True
return False


class UploadException:
def __init__(self,rsn): self.reason = rsn

NO_FILE_FIELD = -1
NO_FILENAME = -2
BAD_EXTENTION = -3
NO_FILE = -4


def process_fileitem( file_item_name, local_file_path = './', allowed_file_types = 'jpg' ):
"""Gets file from form field file_item_name and saves it with the original
file name to local_file_path. Returns (file_length,file_name) if success.
Otherwise (NO_FIELD|NO_FILE|BAD_EXT < 0, info)
"""

form = cgi.FieldStorage()
if not form.has_key( file_item_name ):
raise UploadException( NO_FILE_FIELD )

file_item = form[ file_item_name ]

if not file_item.filename:
raise UploadException( NO_FILENAME )

remote_file_name = file_item.filename
file_name = strip_path( remote_file_name )

if not check_ext( file_name, allowed_file_types ):
raise UploadException( BAD_EXTENTION )

local_file_name = os.path.join( local_file_path, file_name )

if not file_item.file:
raise UploadException( NO_FILE )

data = file_item.file.read( 5*1024*1024 ) # max 5 megabyte
# or data = fileitem.value
# or data = form.getvalue( file_item_name, "" )

fstrm = open( local_file_name, "wb" )
fstrm.write( data )
fstrm.close()

return (len(data), file_name)


print "<html><head><title>Upload form</title></head><body>"

try:

file_field_name = "filename"
loc_path = "../upload"
file_types = "txt,htm,html,png,gif,jpg,ico,zip,rar,avi,mpg,rm,ram,wma,mp3,wav,pdf,doc,ppt"

try:

flen, fname = process_fileitem( file_field_name, loc_path, file_types )
print '%d bytes received to <a href="%s/%s">%s</a>' % \
(flen, loc_path, fname, fname)

except UploadException, ex:

if ex.reason == NO_FILE_FIELD or ex.reason == NO_FILENAME:
print "<p>Browse for file to upload.</p>"
elif ex.reason == BAD_EXTENTION:
print "<p>Illegal file, only %s allowed.</p>" % file_types
else: # NO_FILE
print "<p>No file received. Please repeat.</p>"
print the_form % (strip_path( __file__ ), file_field_name)

except:

print "<html><body text=red bgcolor=white><pre>"
sys.stderr = sys.stdout
traceback.print_exc()
print "</pre></body></html>"

print "</body></html>"


# EOF
 
J

John J. Lee

Georgy Pruss said:
| Hi,
|
| I am curious how one might submit a JPEG to a web site using Python.
| I've tried urllib.urlopen, passing a dictionary that contained a key
| pointing to a string that contains the bytes of the JPEG, but that
| didn't apparently work.

No -- you need to give urllib (or urllib2, better) the raw data to be
posted, which should be MIME multipart/form-data encoded (which
involves adding those funny lines starting with '--'). You also need
appropriate HTTP headers.

| I did use the urllib.urlencode function on the
| dict before calling urlopen. It seems on the face of it that urlopen
| is not the ordained way to do what I want here.

URL encoding is for the other way of uploading form data
(application/x-www-form-urlencoded -- no peculiar MIME encoding in
that case, just foo=bar&spam=eggs). multipart/form-data was invented
because it would be clunky to try to shoehorn both ordinary form
control data and large uploaded, possibly binary, files into the
URL-encoded format.

| The <form> tag of the page I'm submitting to looks like this:
|
| <form action="application_one_process.php" name="mainForm"
| method="POST" enctype="multipart/form-data" accept-charset="US-ASCII">

1. web-sig mailing list archives has a few functions for generating
the appropriate data to pass to urlopen. You then just have to
have the appropriate HTTP headers (I forget, but I think just
Content-Type).

2. ClientForm (assuming you don't mind urlopening the web page with
the form each time you want to submit it -- alternatively, keep the
web page or just the form in a string or local file and use
ClientForm.ParseFile, or pickle the HTMLForm objects, or whatever):

http://wwwsearch.sf.net/ClientForm/

r = urllib2.urlopen("http://www.example.com/form.html")
forms = ClientForm.ParseResponse(r)
r.close()
form = forms[0]

f = open("data.dat")
form.add_file(f, "text/plain", "data.dat")
request = form.click()
r2 = urllib2.urlopen(request)
f.close()
print r2.read()
r2.close()


[...]
It's not a "product version", but it works at my site (Windows XP, [...]
print "Content type: text/html"
print
[...]


Georgy, Steve was asking about about the client side. An easy mistake
to make, I know...


John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,169
Messages
2,570,920
Members
47,463
Latest member
FinleyMoye

Latest Threads

Top