class OddJob::FileUpload

Webrick servlet for upload pages.

Public Class Methods

new(server, delay, save_directory, *options) click to toggle source

Standard servlet initialization function with additional arguments.

delay is the seconds of simulated network delay to wait before responding after an upload request.

save_directory is the the directory location to save uploaded files. If save_directory is set to nil uploaded files are not save, instead the entire http request is printed on STDOUT, followed by the name and contents of each file. Generally only useful for small and non-binary files.

Calls superclass method
# File lib/oddjob.rb, line 178
def initialize(server, delay, save_directory, *options)
  @simulated_delay = delay
  @save_directory = save_directory
  super(server, options)
end

Public Instance Methods

do_GET(request, response) click to toggle source

Serves a simple file upload form. Uploads submitted are handled by this class’ do_Post method.

# File lib/oddjob.rb, line 229
def do_GET(request, response)
  response.status = 200
  response['Content-type'] = 'text/html'
  response.body = uploader_page
end
do_POST(request, response) click to toggle source

Handles webrick post request when uploading one or more files via a standard HTML form submission. The form should include an input of type ‘file’. See the page produced by the do_GET method for an example form.

# File lib/oddjob.rb, line 188
def do_POST(request, response)

  if @save_directory.nil?   # Request to server STDOUT.
    puts "-- BEGIN File Upload POST Request --"
    puts request
    puts "-- END File Upload POST Request --"
  end

  all_uploads = Array.new
  ['file', 'file[]'].each do |name|
    if request.query[name]
      request.query[name].each_data do |data|
        upload = OpenStruct.new
        upload.name = data.filename

        if @save_directory.nil? # File contents to server STDOUT.
          puts "== BEGIN #{data.filename} Contents =="
          puts data.to_s
          puts "== END #{data.filename} Contents =="
        else
          output_name = unique_name(data.filename, @save_directory)
          File.open(output_name, "w"){|f| f.print(data.to_s)}
          puts "#{data.filename} uploaded, saved to #{output_name}"
          upload.output_name = File.expand_path(output_name)
        end

        all_uploads.push(upload)
      end
    end
  end

  response.status = 200
  response['Content-type'] = 'text/html'
  response.body = uploaded_page(all_uploads)

  sleep(@simulated_delay)
end

Protected Instance Methods

unique_name(desired_name, save_directory) click to toggle source

Finds a unique name in the same directory for the given file.

The uploaded file will be renamed if a file by that name already exists. An index number is added to the file’s base name to make it unique. For example if test.txt already existed then test_1.txt would be checked, followed by test_2.txt, and so on.

# File lib/oddjob.rb, line 244
def unique_name(desired_name, save_directory)
  ext = File.extname(desired_name)
  base = File.basename(desired_name, ext)

  final_base = full_base = File.join(save_directory, base)
  i = 1
  while File.exist?(final_base + ext)
    final_base = "#{full_base}_#{i}"
    i += 1
  end

  final_base + ext
end
uploaded_page(uploads) click to toggle source

Returns a string holding the result of the upload page submission.

names is an array of the uploaded file names. These are names as submitted. Saved names may be different to avoid overwritting.

# File lib/oddjob.rb, line 306
def uploaded_page(uploads)
  html = [
    "<h2>Results</h2>",
    "<p>Uploaded:</p>",
    "<ul>",
  ]

  uploads.each do |upload|
    html += [
      "<li>",
      "<strong>#{upload.name}</strong>",
      upload.output_name ? " - saved to: #{upload.output_name}" : "",
      "</li>",
    ]
  end

  html += [
    "</ul>",
    "<p><a href=''>Return to upload page</a></p>",
  ]

  page(html, "Upload Results")
end
uploader_page() click to toggle source

Returns a string holding the full HTML page with the file upload form.

# File lib/oddjob.rb, line 260
def uploader_page
  html = [
    "<h2>Oddjob File Uploader</h2>",
    "<form action='' method='POST' enctype='multipart/form-data'>",
    "    <label for='file'>Select one or more files to upload:</label>",
    "    <br><br>",
    "    <input type='file' name='file' multiple='true'>",
    "    <br><br>",
    "    <input type='submit' value='Upload'>",
    "</form>",
    "<br>",
  ]

  if @save_directory.nil?
    html += [
      "<p class=\"fineprint\">",
      "Currently file uploads will <strong>not</strong> be saved, instead",
      "their contents will be printed to oddjob's standard output.",
      "In this configuration it is recommended that you only upload",
      "text files.",
      "</p>",
      "<p class=\"fineprint\">",
      "To upload any kind of file (binary or text) specify an output",
      "directory where files will be saved instead.  To see how visit the",
      "<a href=\"#{INFO_PATH}\">info page</a>.",
      "</p>",
    ]
  else
    html += [
      "<p class=\"fineprint\">",
      "Uploaded files will be saved in the",
      "<strong>#{File.expand_path(@save_directory)}</strong> directory.",
      "New files do not overwrite existing ones, instead they are given",
      "a unique numbered suffix.",
      "</p>",
    ]
  end

  page(html, "Uploader")
end