How to file upload via http?
[1/8] from: jason:cunliffe:verizon at: 21-Aug-2002 23:45
Does anyone have an example of a rebol server-side script to handle file upload
via http ?
For example, an HTML page with a form:
<form method="post" action="savefile.r" enctype="multipart/form-data" />
<p>Select an image or script file to upload </p>
<fieldset>
<legend>File to upload:<br /></legend>
<input type="hidden" name="MAX_SIZE" value="50000" /><br/>
<input type="file" name="FILE_NAME" size="50" /><br/>
<input type="submit" value="UPLOAD FILE" /><br/>
</fieldset>
</form>
What should %savefile.r look like?
thanks
./Jason
[2/8] from: gchiu:compkarori at: 22-Aug-2002 17:09
>What should %savefile.r look like?
I can't recall if I've made any changes to this, but I
recall testing it and I think it worked for me.
#!/path/to/rebol -cs
REBOL [
Title: "multipart POST"
Date: 15-Sep-1999
Version: 1.2
File: %POST.r
Author: "Andrew Grossman (modified by: Luis Rodriguez J
-.29-April-2000)"
Email: [grossdog--dartmouth--edu]
Owner: "REBOL Technologies"
Purpose: {
To decode multipart encoded POST requests,
including file uploads.
}
Usage: {
Call this file in your CGI scriptand do
decode-multi with a
file argument of the directory where uploaded
files will go and
a logic argument to set whether files will be
given the field they
were
uploaded as as a name. Files are saved and
variables are decoded
and
set.
}
Notes: {
Fixed problem recognizing EOF.
Functionality is now rock solid. Function
calls won't change, so this is certainly useable.
See the comment in the decode-multi function if
you need mime types.
Tested with MSIE and Netscape for Mac.
}
category: ['web 'cgi 'utility]
]
print "Content-Type: text/html^/^/"
print {<HTML><BODY>}
decode-multi: func [
file-dir [file!] {Directory in which to put uploaded
files}
save-as-field [logic!] {save files as field name or
uploaded filename}
/local str boundary done name file done2 content
] [
if equal? system/options/cgi/request-method "POST" [
either not parse system/options/cgi/content-type
["multipart/form-data" skip thru {boundary=} skip some {-}
copy boundary to end]
; not multipart
[str: make string! input do decode-cgi str]
[
print "Decoding multipart data"
str: make string! input
done: false
while [not done] [
name: make string! ""
str: make string! input
either equal? "" str
[done: true]
[
either parse/all str [skip thru {name="} copy name to
{"}
skip thru {filename="} copy file to {"} skip to end]
[
str: make string! input
if not equal? str "" [str: make string! input]
comment {if you need mime put "parse/all str
["Content-Type:"
skip copy mime to end]" into the
preceding if
block.}
done2: false
content: make string! ""
while [not done2] [
content-length: to-integer
system/options/cgi/content-length
str: make string! content-length
read-io system/ports/input str content-length
either d: find/reverse tail str boundary [
e: find/reverse tail copy/part str (index? d)
{^/}
content: copy/part str (index? e) - 2
done2: true]
[
append content str
]
]
write/binary %content.bin str
if not none? file [
either save-as-field [name: dehex name write/binary
file-dir/:name content] [
file: dehex file write/binary file-dir/:file
content
]
]
] [
parse str [skip thru {name="} copy name to {"}]
str: make string! input str: dehex make string!
input
set to-word name str str: make string! input
]
]
]
]
]
] ; of If Post
decode-multi %. true
print "Form Processed"
print {</BODY></HTML>}
--
Graham Chiu
[3/8] from: jason:cunliffe:verizon at: 22-Aug-2002 4:55
Thanks Graham
Yes multipart %post.r script looks like the business..
It's _almost_ working. But I keep getting this error ->
Decoding multipart data ** Access Error: Cannot open
/web/turbulence/www/Works/trees/vanilla/content.bin ** Where: decode-multi **
Near: write/binary %content.bin str if not
I think somthing to do with the MIME types. There's a comment in the script for
changing an 'if' statement, but I don't grok it yet.
Any ideas?
./Jason
[4/8] from: gchiu:compkarori at: 23-Aug-2002 9:09
>Yes multipart %post.r script looks like the business..
>It's _almost_ working. But I keep getting this error ->
>
>Decoding multipart data ** Access Error: Cannot open
>/web/turbulence/www/Works/trees/vanilla/content.bin **
>Where: decode-multi **
>Near: write/binary %content.bin str if not
Hi Jason,
You sure it's not a permissions problem?
Perhaps stick in a line to write a few bytes to another
file in the same directory to see what happens...
--
Graham Chiu
[5/8] from: andreas:bolka:gmx at: 22-Aug-2002 23:04
Thursday, August 22, 2002, 5:45:09 AM, Jason wrote:
> Does anyone have an example of a rebol server-side script to handle file upload
> via http ?
I've a 'decode-multipart-form-data avail (as I guess that you are
interested in this becaus of vanillla, this will be distributed with
vanilla 0.5.2)
I guess for a simple savefile CGI this will be a bit harder to use
than %POST.r, but I think decode-multipart-form-data is a cleaner
approach - let me know what you think!
Here it is:
-- snip --
REBOL [
Title:
"decode-multipart-form-data"
Authors:
[ "Andreas Bolka" ]
Contributors:
[ ]
Date:
2002-06-18
Version:
1.1
Purpose: {
Decodes POST-data encoded as "multipart/form-data" as defined by
RFC 2388.
The output is compatible to 'decode-cgi wherever possible. So the
output contains a list of set-word's and values, one pair for each data
field. example:
[ field1: "foo" field2: "bar" ]
If the content type of one part of the form-data is not equal to
text/plain, then the value of the respective mime-part is an
object! with the following attribs: filename, type, content. example:
[ field1: "foo"
field2: make object! [
filename: "user.xml"
type: "text/xml"
content: "<?xml version='1.0'><user />"
]
]
}
]
decode-multipart-form-data: func [
p-content-type
p-post-data
/local list ct pd bd delim-beg delim-end mime-part
] [
list: copy []
if not found? find p-content-type "multipart/form-data" [ return list ]
ct: copy p-content-type
pd: copy p-post-data
bd: join "--" copy find/tail ct "boundary="
delim-beg: join crlf crlf
delim-end: rejoin [ crlf bd ]
mime-part: [
( ct-dispo: content: none ct-type: "text/plain" )
thru bd
thru "content-disposition: " copy ct-dispo to crlf
opt [ thru "content-type: " copy ct-type to crlf ]
thru delim-beg copy content to delim-end
( handle-mime-part ct-dispo ct-type content )
]
handle-mime-part: func [ p-ct-dispo p-ct-type p-content /local fieldname ] [
p-ct-dispo: parse p-ct-dispo {;="}
fieldname: select p-ct-dispo "name"
append list to-set-word fieldname
either found? find p-ct-type "text/plain" [
append list content
] [
append list make object! [
filename: select p-ct-dispo "filename"
type: copy p-ct-type
content: either none? p-content [ none ] [ copy p-content ]
]
]
]
use [ ct-dispo ct-type content ] [
parse/all pd [ some mime-part ]
]
list
]
-- snap --
--
Best regards,
Andreas mailto:[andreas--bolka--gmx--net]
[6/8] from: jason::cunliffe::verizon::net at: 22-Aug-2002 18:34
Hi Graham
Yes - I needed to flip permission bit on the directory it was in :)
thanks
./Jason
[7/8] from: jason:cunliffe:verizon at: 22-Aug-2002 18:38
Andreas
Thanks for the new multiform data code.
It must dinner time because my brain is getting slow..
Can you help me understand how to use it?
thanks
./Jason
[8/8] from: andreas:bolka:gmx at: 23-Aug-2002 17:40
Friday, August 23, 2002, 12:38:09 AM, Jason wrote:
> Can you help me understand how to use it?
-- snip --
; first you fetch the post-data (the HTTP POST entity body,
; to be correct) as always
len: load any [ system/options/cgi/content-length "0"]
post-data: make string! (len + 10)
while [len > 0][ len: len - read-io system/ports/input post-data len ]
; then this POST-data can be handed over to decode-multipart-form-data
; (if it is encoded according to the mime multipart RFC's as
; indicated by a content type beeing multipart/form-data)
tmp-post: either found? find any [ system/options/cgi/content-type "" ] "multipart/form-data"
[ decode-multipart-form-data system/options/cgi/content-type post-data ]
[ decode-cgi post-data ]
-- snap --
after that you'll have a decode-cgi like structure in tmp-post which
is described in full detail in the headers of the script i posted
before:
-- snip --
Purpose: {
Decodes POST-data encoded as "multipart/form-data" as defined by
RFC 2388.
The output is compatible to 'decode-cgi wherever possible. So the
output contains a list of set-word's and values, one pair for each data
field. example:
[ field1: "foo" field2: "bar" ]
If the content type of one part of the form-data is not equal to
text/plain, then the value of the respective mime-part is an
object! with the following attribs: filename, type, content. example:
[ field1: "foo"
field2: make object! [
filename: "user.xml"
type: "text/xml"
content: "<?xml version='1.0'><user />"
]
]
}
-- snap --
--
Best regards,
Andreas mailto:[andreas--bolka--gmx--net]