Ruby/Webrick File upload using multipart/form-data

Sunday, January 25, 2009

One of the challenges I'm running into with Ruby is that there isn't the same level of reference documentation as there is in Java. It took me far too long to work out how to implement HTTP multipart file upload in Ruby so I'm posting the code here in the hope that it is useful for others.

The following Ruby source is for a web server with a file upload servlet that accepts multpart/form-data file uploads.

#!/usr/local/bin/ruby
require 'webrick'
require 'stringio'
include WEBrick

s = HTTPServer.new( :Port => 8090 )

class FileUploadServlet < HTTPServlet::AbstractServlet
def do_POST(req, res)
filedata= req.query["filename"]

f = File.open("foo.out", "wb")
f.syswrite req.filedata
f.close

puts "Saved file OK"
end
end
s.mount("/upload", FileUploadServlet)

trap("INT"){ s.shutdown }
s.start


This is the HTML form to test this servlet with


<form action="http://localhost:8090/upload" method="POST" enctype="multipart/form-data">
File: <input type="file" name="filename"><br/>
<input type="submit" value="Upload">
</form>

Labels:


FireStorm now supports Ruby

Wednesday, January 21, 2009

FireStorm/DAO 4.0.1 includes a Ruby DAO code generator for MySQL (using the mysql-ruby library to interact with the database). To see sample generated Ruby DAO code, take a look at this MySQL-Ruby Tutorial.

The new release is available to download here.

Labels:


Python first impressions

Wednesday, January 14, 2009

Over the past couple of months I have started developing in Python and to a lesser degree so far, Ruby. I have mostly only used strongly typed compiled languages, namely C++ and Java throughout my career and have often resisted doing anything in scripting languages that I felt I could do in Java or C++, mostly because I'm already proficient in those languages and I rarely have too much time for non-essential learning curves.

However, I am now building some tooling for dbShards, our database sharding, replication, and failover solution, using Python. The main reason for choosing Python over Java is that we wanted a lightweight framework that makes it easy to monitor and control operating system processes on remote servers. Python was recommended to me by a friend (thanks, Paul!) and so far it looks like a pretty good choice, although I'm sure Ruby would also have been a good choice for this project.

Both Python and Ruby are object oriented to varying degrees but both allow good object oriented design and implementation making it easy for Java developers to pick up the language. The Python syntax has a couple of things that don't feel too natural, such as constructors being called __init__() and the fact that all non-static methods on a class must have a 'self' parameter rather than having a built in 'this' attribute as in Java. Neither of these is really a problem at all and they soon start to feel natural enough. The only real bugbear I have have with the Python language itself is the indentation syntax - Python purely relies on indentation (tabs and spaces) in the code to determine nesting rather than using curly braces or any other form of begin/end syntax. As a result, I find myself constantly switching between text editors and vi to fix indenting issues at the moment. I will have to spend some time researching IDEs for Python (so far I have been using the IntelliJ plugin, the PyDev plugin for Eclipse, and TextMate and none of them seem great at preserving the indents correctly). If anyone has any recommendations for Python tools please let me know.

Those issues aside, Python is a nice language and easy to learn. Most tasks can be implemented faster than the same tasks using Java, but not to the degree that many report (I have seen many claims of 5-10x productivity gains over Java and these might be true for someone who is not proficient in Java I suppose). The bigger challenge is the Python standard library which is very poorly documented. I spent almost a full day yesterday implementing a web server that supports "multipart/form-data" using the built-in BaseHTTPServer and cgi classes based on the documentation. I think the main issue was that I was using version 3.0 and it appears that this release is perhaps a bit too new to be used for production. When I ported my code back to version 2.5.1 it worked fine.

Python is undergoing some major changes at the moment and version 3.0 was released just a few weeks ago. There are some pretty fundamental changes between version 2.6.x and 3.0 such as "print" changing from being a statement to being a function, that make it impractical, to say the least, to write code that can work with both versions.

I have decided to stick with version 2.5.1 for now and port my code at a later date once 3.0 is stable enough (and once binary distributions are available for the platforms we need to support).

Eclipse "Unable to load default SVN Client"

Monday, January 5, 2009

After performing a fresh install of Eclipse Ganymede and Subclipse on Fedora 10, I get the error "Unable to load default SVN Client" when trying to import a project. After installing "JavaHL Adapter", "SVNKit" and "JNA Library" whatever those are it now works. Surely these should be flagged as "required" rather than "optional" or "recommended"?

Fedora 10 network configuration is broken

And the new year gets off to a frustrating start ... I installed Fedora 10 on one of my QA machines this weekend and ran into some problems today when I attempted to change the network settings to use static IP. It turns out that the GUI network configuration tool is broken in Fedora 10 and does not save the netmask value (it seems to write the gateway IP address to the netmask field in the configuration file). The workaround for this issue was simply to edit /etc/sysconfig/network-scripts/ifcfg-eth0 manually and enter the correct netmask value. Unfortunately I wasted half an hour before realising what the problem was. My day can only get better.

Relocation to Colorado

Sunday, January 4, 2009

My blog has been rather quiet lately. The main reason for this is that I relocated from England to Colorado in September with my family as a result of some changes at CodeFutures which I will blog about soon. It's an incredibly exciting time both for CodeFutures and for me personally.