Ruby cgi and forms question

I have a form that contains both text fields and a file field for
uploading. The form is set to post to a ruby script on my server. The
script works(excluding file uploading) when I delete
ENCTYPE="multipart/form-data" from the form tag but if that is
present(and it needs to be for the image upload to work) then ruby cgi
chokes on a gsub for one of my text field parameters called comment.

imageadmin.rb:14: private method `gsub!' called for
#<StringIO:0x20221278> (NoMethodError)

Anyone have some ideas for how I can make this work?

Here is the form code (it is from an eruby file)

···

-----------------------------------------------------
% imageArray = Dir.glob("*.jpg").sort!
% commentArray = imageArray.collect {|image| image[4..-5]}
% commentArray.collect {|image| image.gsub!("_", " ")}

<FORM ENCTYPE="multipart/form-data" action="imageadmin.rb" method="post">
<%imageArray.length.times do |count|%>
  <img src="<%=imageArray[count]%>">
  <BR />
  Comment:<input type="text" name="comment"
value="<%=commentArray[count]%>">
  <BR />
  Number:<input type="text" name="order"
value="<%=imageArray[count][0..2] %>">
  <BR />
  Delete:<input type="checkbox" name="delete"
value="<%=imageArray[count]%>">
  <BR />
<%end%>
<BR />
<BR />
<input type="file" value="upload">
Comment:<input type="text" name="uploadcomment" value="">

<BR />
<input type="submit" value="Submit">
</FORM>
-----------------------------------------------------------------

And here is the script itself. I apologize for the lack of comments and
that it isn't as short as it could be. I am going to clean it up tonight.
-----------------------------------------------------------------------
#!/usr/bin/env ruby
$stderr = File.open("error.log", "w+")
print "Content-type: text/html\n\n"
require 'cgi'
cgi = CGI.new

deleteArray = cgi.params['delete']
imageArray = Dir.glob("*.jpg").sort!
oldArray = Dir.glob("*.jpg").sort!
commentArray = cgi.params['comment']

#####Here is where I get the error#####
commentArray.each {|com| com.gsub!(" ", "_")}
numberArray = cgi.params['order']

count = imageArray.length

count.times do |x|
  imageArray[x].sub!(/^\d\d\d/, numberArray[x])
end

count.times do |x|
  imageArray[x] = numberArray[x] + "_" + commentArray[x] + ".jpg"
end

count.times do |x|
  File.rename(oldArray[x], imageArray[x])
end

#uploadImage = cgi['upload']
#if uploadImage
# ucomments = cgi.params['uploadcomment']
# ucomments.each {|com| com.gsub!(" ", "_")}
# image = File.new("#{ucomments}.jpg", "w+")
# image << uploadImage
# image.close
#end

for thing in deleteArray
  File.delete(thing)
end

print "<meta HTTP-EQUIV=\"REFRESH\" content=\"0; url=admin.rhtml\">"

-------------------------------------------------------------------

Thank you,
Matthew Margolis

If I recall correctly, multi-part form data comes as type StringIO,
not String. Check out
http://www.ruby-doc.org/stdlib/libdoc/stringio/rdoc/ for RDoc
documentation on StringIO. You can probably get the string by
StringIO.read.

require 'stringio'
a = StringIO.new( "foo")
a.read

will give "foo"

···

On Wed, 26 Jan 2005 02:55:14 +0900, MATTHEW REUBEN MARGOLIS <mrmargolis@wisc.edu> wrote:

I have a form that contains both text fields and a file field for
uploading. The form is set to post to a ruby script on my server. The
script works(excluding file uploading) when I delete
ENCTYPE="multipart/form-data" from the form tag but if that is
present(and it needs to be for the image upload to work) then ruby cgi
chokes on a gsub for one of my text field parameters called comment.

imageadmin.rb:14: private method `gsub!' called for
#<StringIO:0x20221278> (NoMethodError)

Anyone have some ideas for how I can make this work?

Here is the form code (it is from an eruby file)
-----------------------------------------------------
% imageArray = Dir.glob("*.jpg").sort!
% commentArray = imageArray.collect {|image| image[4..-5]}
% commentArray.collect {|image| image.gsub!("_", " ")}

<FORM ENCTYPE="multipart/form-data" action="imageadmin.rb" method="post">
<%imageArray.length.times do |count|%>
  <img src="<%=imageArray[count]%>">
  <BR />
  Comment:<input type="text" name="comment"
value="<%=commentArray[count]%>">
  <BR />
  Number:<input type="text" name="order"
value="<%=imageArray[count][0..2] %>">
  <BR />
  Delete:<input type="checkbox" name="delete"
value="<%=imageArray[count]%>">
  <BR />
<%end%>
<BR />
<BR />
<input type="file" value="upload">
Comment:<input type="text" name="uploadcomment" value="">

<BR />
<input type="submit" value="Submit">
</FORM>
-----------------------------------------------------------------

And here is the script itself. I apologize for the lack of comments and
that it isn't as short as it could be. I am going to clean it up tonight.
-----------------------------------------------------------------------
#!/usr/bin/env ruby
$stderr = File.open("error.log", "w+")
print "Content-type: text/html\n\n"
require 'cgi'
cgi = CGI.new

deleteArray = cgi.params['delete']
imageArray = Dir.glob("*.jpg").sort!
oldArray = Dir.glob("*.jpg").sort!
commentArray = cgi.params['comment']

#####Here is where I get the error#####
commentArray.each {|com| com.gsub!(" ", "_")}
numberArray = cgi.params['order']

count = imageArray.length

count.times do |x|
  imageArray.sub!(/^\d\d\d/, numberArray)
end

count.times do |x|
  imageArray = numberArray + "_" + commentArray + ".jpg"
end

count.times do |x|
  File.rename(oldArray, imageArray)
end

#uploadImage = cgi['upload']
#if uploadImage
# ucomments = cgi.params['uploadcomment']
# ucomments.each {|com| com.gsub!(" ", "_")}
# image = File.new("#{ucomments}.jpg", "w+")
# image << uploadImage
# image.close
#end

for thing in deleteArray
  File.delete(thing)
end

print "<meta HTTP-EQUIV=\"REFRESH\" content=\"0; url=admin.rhtml\">"

-------------------------------------------------------------------

Thank you,
Matthew Margolis

Ok that worked. Now my problem is just getting the uploaded image into a file. I am trying to do

uploadImage = cgi['upload']
if uploadImage
  ucomments = cgi.params['uploadcomment']
  ucomments.each {|com| com.gsub!(" ", "_")}
  image = File.new("#{ucomments}.jpg", "w+")
  image << uploadImage
  image.close
end

But I always end up with a 0 length .jpg though it is named right. cgi['upload'] is StringIO.

-Matthew Margolis

Belorion wrote:

···

If I recall correctly, multi-part form data comes as type StringIO,
not String. Check out
http://www.ruby-doc.org/stdlib/libdoc/stringio/rdoc/ for RDoc
documentation on StringIO. You can probably get the string by
StringIO.read.

require 'stringio'
a = StringIO.new( "foo")
a.read

will give "foo"

On Wed, 26 Jan 2005 02:55:14 +0900, MATTHEW REUBEN MARGOLIS ><mrmargolis@wisc.edu> wrote:

I have a form that contains both text fields and a file field for
uploading. The form is set to post to a ruby script on my server. The
script works(excluding file uploading) when I delete
ENCTYPE="multipart/form-data" from the form tag but if that is
present(and it needs to be for the image upload to work) then ruby cgi
chokes on a gsub for one of my text field parameters called comment.

imageadmin.rb:14: private method `gsub!' called for
#<StringIO:0x20221278> (NoMethodError)

Anyone have some ideas for how I can make this work?

Here is the form code (it is from an eruby file)
-----------------------------------------------------
% imageArray = Dir.glob("*.jpg").sort!
% commentArray = imageArray.collect {|image| image[4..-5]}
% commentArray.collect {|image| image.gsub!("_", " ")}

<FORM ENCTYPE="multipart/form-data" action="imageadmin.rb" method="post">
<%imageArray.length.times do |count|%>
<img src="<%=imageArray[count]%>">
<BR />
Comment:<input type="text" name="comment"
value="<%=commentArray[count]%>">
<BR />
Number:<input type="text" name="order"
value="<%=imageArray[count][0..2] %>">
<BR />
Delete:<input type="checkbox" name="delete"
value="<%=imageArray[count]%>">
<BR />
<%end%>
<BR />
<input type="file" value="upload">
Comment:<input type="text" name="uploadcomment" value="">

<BR />
<input type="submit" value="Submit">
</FORM>
-----------------------------------------------------------------

And here is the script itself. I apologize for the lack of comments and
that it isn't as short as it could be. I am going to clean it up tonight.
-----------------------------------------------------------------------
#!/usr/bin/env ruby
$stderr = File.open("error.log", "w+")
print "Content-type: text/html\n\n"
require 'cgi'
cgi = CGI.new

deleteArray = cgi.params['delete']
imageArray = Dir.glob("*.jpg").sort!
oldArray = Dir.glob("*.jpg").sort!
commentArray = cgi.params['comment']

#####Here is where I get the error#####
commentArray.each {|com| com.gsub!(" ", "_")}
numberArray = cgi.params['order']

count = imageArray.length

count.times do |x|
imageArray.sub!(/^\d\d\d/, numberArray)
end

count.times do |x|
imageArray = numberArray + "_" + commentArray + ".jpg"
end

count.times do |x|
File.rename(oldArray, imageArray)
end

#uploadImage = cgi['upload']
#if uploadImage
# ucomments = cgi.params['uploadcomment']
# ucomments.each {|com| com.gsub!(" ", "_")}
# image = File.new("#{ucomments}.jpg", "w+")
# image << uploadImage
# image.close
#end

for thing in deleteArray
File.delete(thing)
end

print "<meta HTTP-EQUIV=\"REFRESH\" content=\"0; url=admin.rhtml\">"

-------------------------------------------------------------------

Thank you,
Matthew Margolis

Belorion wrote:

If I recall correctly, multi-part form data comes as type StringIO,
not String.

It's either that, or a Tempfile (for larger files). Tempfile is also an IO, but instead of reading it (and presumably copying somewhere) you can move the file itself - which is much faster.

···

--
Best regards,

Alexey Verkhovsky

Ruby Forum: http://ruby-forum.org (moderator)
RForum: http://rforum.andreas-s.net (co-author)
Instiki: http://instiki.org (maintainer)

I highly recommend checking out this site:

http://www.zytrax.com/tech/lang/ruby/#upload

Also, I had some issues with image upload, storage, and retrieval.
These issues where discussed in this thread, which includes loading
binary data for display in a browser:

http://groups-beta.google.com/group/comp.lang.ruby/browse_thread/thread/924b262641d661e4/172f1b0d03610b78?q=mysql+binary+belorion&_done=%2Fgroup%2Fcomp.lang.ruby%2Fsearch%3Fgroup%3Dcomp.lang.ruby%26q%3Dmysql+binary+belorion%26qt_g%3D1%26searchnow%3DSearch+this+group%26&_doneTitle=Back+to+Search&&d#172f1b0d03610b78

I can't say for sure, but a first glance I think you need

image << uploadImage.read

Give that a shot, let us know if you get it working.

It's a similar discussion when I was going through the same stuff you
are right now.

···

On Wed, 26 Jan 2005 05:44:20 +0900, Matthew Margolis <mrmargolis@wisc.edu> wrote:

Ok that worked. Now my problem is just getting the uploaded image into
a file. I am trying to do

uploadImage = cgi['upload']
if uploadImage
  ucomments = cgi.params['uploadcomment']
  ucomments.each {|com| com.gsub!(" ", "_")}
  image = File.new("#{ucomments}.jpg", "w+")
  image << uploadImage
  image.close
end

But I always end up with a 0 length .jpg though it is named right.
cgi['upload'] is StringIO.

-Matthew Margolis

Belorion wrote:

>If I recall correctly, multi-part form data comes as type StringIO,
>not String. Check out
>http://www.ruby-doc.org/stdlib/libdoc/stringio/rdoc/ for RDoc
>documentation on StringIO. You can probably get the string by
>StringIO.read.
>
>require 'stringio'
>a = StringIO.new( "foo")
>a.read
>
>will give "foo"
>
>
>On Wed, 26 Jan 2005 02:55:14 +0900, MATTHEW REUBEN MARGOLIS > ><mrmargolis@wisc.edu> wrote:
>
>
>>I have a form that contains both text fields and a file field for
>>uploading. The form is set to post to a ruby script on my server. The
>>script works(excluding file uploading) when I delete
>>ENCTYPE="multipart/form-data" from the form tag but if that is
>>present(and it needs to be for the image upload to work) then ruby cgi
>>chokes on a gsub for one of my text field parameters called comment.
>>
>>imageadmin.rb:14: private method `gsub!' called for
>>#<StringIO:0x20221278> (NoMethodError)
>>
>>Anyone have some ideas for how I can make this work?
>>
>>Here is the form code (it is from an eruby file)
>>-----------------------------------------------------
>>% imageArray = Dir.glob("*.jpg").sort!
>>% commentArray = imageArray.collect {|image| image[4..-5]}
>>% commentArray.collect {|image| image.gsub!("_", " ")}
>>
>><FORM ENCTYPE="multipart/form-data" action="imageadmin.rb" method="post">
>><%imageArray.length.times do |count|%>
>> <img src="<%=imageArray[count]%>">
>> <BR />
>> Comment:<input type="text" name="comment"
>>value="<%=commentArray[count]%>">
>> <BR />
>> Number:<input type="text" name="order"
>>value="<%=imageArray[count][0..2] %>">
>> <BR />
>> Delete:<input type="checkbox" name="delete"
>>value="<%=imageArray[count]%>">
>> <BR />
>><%end%>
>><BR />
>><BR />
>><input type="file" value="upload">
>>Comment:<input type="text" name="uploadcomment" value="">
>>
>><BR />
>><input type="submit" value="Submit">
>></FORM>
>>-----------------------------------------------------------------
>>
>>And here is the script itself. I apologize for the lack of comments and
>>that it isn't as short as it could be. I am going to clean it up tonight.
>>-----------------------------------------------------------------------
>>#!/usr/bin/env ruby
>>$stderr = File.open("error.log", "w+")
>>print "Content-type: text/html\n\n"
>>require 'cgi'
>>cgi = CGI.new
>>
>>deleteArray = cgi.params['delete']
>>imageArray = Dir.glob("*.jpg").sort!
>>oldArray = Dir.glob("*.jpg").sort!
>>commentArray = cgi.params['comment']
>>
>>#####Here is where I get the error#####
>>commentArray.each {|com| com.gsub!(" ", "_")}
>>numberArray = cgi.params['order']
>>
>>count = imageArray.length
>>
>>count.times do |x|
>> imageArray.sub!(/^\d\d\d/, numberArray)
>>end
>>
>>count.times do |x|
>> imageArray = numberArray + "_" + commentArray + ".jpg"
>>end
>>
>>count.times do |x|
>> File.rename(oldArray, imageArray)
>>end
>>
>>#uploadImage = cgi['upload']
>>#if uploadImage
>># ucomments = cgi.params['uploadcomment']
>># ucomments.each {|com| com.gsub!(" ", "_")}
>># image = File.new("#{ucomments}.jpg", "w+")
>># image << uploadImage
>># image.close
>>#end
>>
>>for thing in deleteArray
>> File.delete(thing)
>>end
>>
>>print "<meta HTTP-EQUIV=\"REFRESH\" content=\"0; url=admin.rhtml\">"
>>
>>-------------------------------------------------------------------
>>
>>Thank you,
>>Matthew Margolis
>>
>>
>>
>>
>
>
>