the problem is in your source i'm afraid. you can call CGI.new more than once
in a script : each call attempts to parse ENV and STDIN according to the cgi
spec. check out the docs for details. the other issue is that if, and only
if, you create a form using multipar the cgi params are either StringIO or
Tempfile objects. this is a good thing. consider a 10GB file upload. you
need a way to determine this. following is one way:
harp:~> cat a.rb
#! /usr/local/bin/ruby
require "cgi"
class Upload
attr_accessor 'cgi'
def initialize
self.cgi = CGI::new 'html4'
file = get 'file'
file ? answer : make_form
end
def make_form
cgi.out {
cgi.html {
cgi.body { "\n" +
cgi.multipart_form{ "\n" +
cgi.file_field("file",40,500000) + "\n" +
cgi.br +
cgi.submit("test it") + "\n"
}
}
}
}
end
def answer
cgi.out {
cgi.html {
cgi.body{ "\n" +
cgi.p{ "This should be the filename : " + param('file').original_filename + "\n" } +
cgi.br
}
}
}
end
def get key
value = param key
value = value.read.strip if value.respond_to?('read')
value
end
def param key
cgi.params[key].first
end
end
Upload::new if $0 == __FILE__
this should run with ruby 1.8 up.
inlined below is a totally simple upload script i sometimes use for personal
stuff. it allows upload/download and some other stuff.
regards.
-a
···
On Fri, 10 Feb 2006, Michael Schilling wrote:
Hello again,
as I couldn't reproduce the described multipart_form error (see
description below) directly on the command-line I looked into the cgi.rb
source and found the chunk of code that raises the exception:
--
happiness is not something ready-made. it comes from your own actions.
- h.h. the 14th dali lama
#! /usr/local/bin/ruby
require 'cgi'
require 'tempfile'
require 'ftools'
require 'uri'
cgi = CGI::new
user = ENV['REMOTE_USER'] || 'anonymous'
headers = {}
content = ''
begin
mode = cgi.params['m'].first || 'index'
mode = mode.read.strip if mode.respond_to? 'read'
case mode
when /index|^$/
files = Dir['**/*'].select{|f| f !~ %r/html|cgi/}
dirname = File::dirname cgi.script_name
files.sort!{|a,b| File::stat(b).mtime <=> File::stat(a).mtime}
table_rows =
files.collect do |f|
stat = File::stat f
uri = 'http://' << cgi.host << File::join(dirname, f)
# <a href=#{ URI::escape f } title="right click -> save as">download</a>
<<-html
<tr valign=top aligh=left>
<td>
#{ CGI::escapeHTML f }
</td>
<td>
#{ CGI::escapeHTML stat.mtime.to_s }
</td>
<td>
#{ CGI::escapeHTML stat.size.to_s }
</td>
<td>
<a href=#{ uri } title="right click -> save (page) as">#{ uri }</a>
</td>
</tr>
html
end
table =
<<-html
<table width=100%>
<tr valign=top aligh=left>
<td> <b><u> file </b></u> </td>
<td> <b><u> modification time </b></u> </td>
<td> <b><u> size </b></u> </td>
<td> <b><u> download </b></u> </td>
</tr>
#{ table_rows }
</table>
html
content = <<-html
<html>
<head>
<title>#{ user }::files</title>
</head>
<body>
<h3>#{ user }::files</h3>
<table cellpadding=1 align=right width=100%>
<tr align=right>
<td>
<i>to download - right click -> save as</i>
</td>
</tr>
</table>
<hr>
<hr>
</table>
<hr>
#{ table }
<hr>
<h3><a href=#{ cgi.script_name }?m=upload>upload files</a></h3>
</body>
</html>
html
when /upload/
buttons =
8.times do
buttons << <<-html
<input size=100 name=file type=file>
<hr width=30% align=left>
html
end
content = <<-html
<html>
<head>
<title>#{ user }::upload</title>
</head>
<body>
<h3>#{ user }::upload</h3>
<hr>
<form action=#{ cgi.script_name } method=POST enctype=multipart/form-data>
<input size=100 name=file type=file>
<hr width=30% align=left>
#{ buttons }
<input type=submit value=upload>
<hr width=30% align=left>
<input type=reset value=clear>
<hr width=30% align=left>
<input type=hidden name=m value=put>
<form>
<hr>
<h3><a href=#{ cgi.script_name }?m=index>index</a></h3>
</body>
</html>
html
when /put/
uploaded =
tempfiles = cgi.params['file']
tempfiles.each do |tempfile|
org_path = tempfile.original_filename
local = "#{ org_path }"
local.gsub! %r|[/\\]|,'/'
local.gsub! %r|\s+|,'_'
local.downcase!
next if local =~ /^\s*$/
begin
File::mkpath(File::dirname(local)) rescue nil
if tempfile.path
File::copy tempfile.path, local
else
open(local,'w'){|f| f.write tempfile.read}
end
File::chmod 0777, local
uploaded << [org_path, true]
rescue
raise
raise tempfile.methods.inspect
uploaded << [org_path, false]
end
end
table_rows =
uploaded.collect do |u|
f, status = u
s = (status ? 'success' : 'failed')
<<-html
<tr valign=top aligh=left>
<td>
#{ CGI::escapeHTML f.inspect }
</td>
<td>
#{ s }
</td>
</tr>
html
end
table =
<<-html
<table width=100%>
<tr valign=top aligh=left>
<td> <b><u> file </b></u> </td>
<td> <b><u> status </b></u> </td>
</tr>
#{ table_rows }
</table>
html
content = <<-html
<html>
<head>
<title>#{ user }::uploaded</title>
</head>
<body>
<h3>#{ user }::uploaded</h3>
</table>
<hr>
#{ table }
<hr>
<h3><a href=#{ cgi.script_name }?m=index>index</a></h3>
</body>
</html>
html
else
content = "#{ cgi.inspect }"
content << '<hr>'
content << cgi.params.inspect
content << '<hr>'
content << cgi.params.map{|key,value| [key.inspect, value.map{|v| [v.inspect, v.class]}.inspect]}.inspect
end
rescue Exception => e
content = "<b>#{ e.message } - (#{ e.class })</b><hr>#{ e.backtrace.join '<br>' }"
ensure
cgi.out{ content.to_s }
end