= Multi Bit Shift Helper
The Multi Bit Shift Helper is designed to make it easy to include either the
Multi Bit Shift or Multi Bit Shift Advanced flash file upload assets in rails
projects. Both Multi Bit Shift and Multi Bit Shift Advanced can be used as form
field plugins, and can replace individual or series of file_fields. The
replacement is not a direct replacement, as a multi_bit_shift_field is designed
to allow any number of files to be uploaded.
Both can also operate as separate applets, and can be integrated without forms.
== Installation
=== Multi Bit Shift
The Multi Bit Shift plugin should be installed from the SVN Release repository.
To install, use the script/plugin method:
ruby script/plugin install http://multibitshift.com/svn/multi_bit_shift_helper/branches/multi_bit_shift/current/multi_bit_shift_helper/
=== Multi Bit Shift Advanced
The Multi Bit Shift Advanced plugin installs both Multi Bit Shift and Multi Bit
Shift Advanced. To install, use the script/plugin method:
ruby script/plugin install http://multibitshift.com/svn/multi_bit_shift_helper/branches/multi_bit_shift_advanced/current/multi_bit_shift_helper/
== Usage
It is recommended that the installation screencasts at
http://multibitshift.com/screencasts be viewed as they provide an extensive
overview of these installation procedures.
=== Basic Requirements
Multi Bit Shift and Multi Bit Shift Advanced don't require our helper plugins to
work, but they do make the applets more manageable. Both plugins are capable of
acting independently and only require that the following methods be implemented
in order to function:
==== 'uploadURL'
URL that files should be uploaded to. The parameters Filename and Filedata are
sent to the url. The applicationToken and the requested Token are also sent to
the url in the parameters token and application_token. It is expected that the
URL responds with either a 200 status if the upload was a success or another
invalid status if the upload failed. The content of the reply does not matter.
We suggest that errors are indicated with the 409 status code. THIS METHOD DOES
NOT PERSIST THE SESSION, see the Session Management section for information
about session validation with file uploads. Defaults to action 'upload_file'.
def upload_file
file_path = "public/uploaded_files"
file_data = params[:Filedata]
file_name = params[:Filename]
if File.exists?(file_path + "/" + file_name)
render(:text => 'error', :status => 409)
# In practice, you probably wouldn't want to throw this error, but it is
# included for demonstration purposes. Do to flash limitations, an actual
# error message can't be returned, so a standard error message is used.
# The text can be customized with the uploadRejectedErrorMessageText, and
# the uploadRejectedErrorTitleText parameters.
else
file_path = "public/uploaded_files"
File.open(file_path + "/" + file_name, "wb") { |new_file| new_file.
write(file_data.read) }
render(:xml => "")
end
end
==== 'removeFileURL'
URL that files should be removed with. This URL is sent a 0 referenced array
file[], that contains the file names of the files to be removed. Multi Bit
Shift Advanced also sends a 0 referenced array id[] that contains the IDs sent
in by the fileList XML. The applicationToken is also sent to the url in the
parameter application_token.
When the upload was successful, Multi Bit Shift
Advanced expects the updated fileList XML to be returned. Multi Bit Shift will
accept any input that is not an error message, although we recommend taht the
xml "" is returned.
On error, both versions expect that an xml error message formatted as
"ContentTitle" be returned.
Both applets will then display a popup error displaying the indicated error
message to the client. The applets expect that the file upload process is
transactional, in the sense that if a single error occurs on any file removal,
it is assumed that all file removals failed. Multi Bit Shift Advanced is
capable of silent failure, only removing a subset of files, then returning
correct xml that lists only the files that presently exist on the server.
Silent failure is discouraged.
Defaults to action 'remove_files'.
def remove_files
@file_path = "public/uploaded_files"
if !params['file'].nil?
params['file'].each_value{|value| value
File.delete(@file_path + "/" + value)
}
end
render :action => "files_on_server"
# No error messages are included in this function. The following code can,
# however, display messages.
# render(:xml => "Bad File RemovalError!")
end
==== 'fileListURL'
This method is only used by Multi Bit Shift Advanced. See the Query String
Parameters below for information about how files are passed into Multi Bit
Shift. URL that lists files. This URL is sent the applicationToken in the
parameter application_token. The applet expects an xml file of the following
format to be returned:
File Name
human readable file size
integer file size in bytes
URL of Image
image or file
any value
URL for icon if file_type is image
The name field is the name of the file. The size is the human readable file
size that is displayed to the user. The bytes field is the size in bytes of the
file. The URL is the URL that the image is loaded from, or that the user is
sent to when they double click the item in the applet. The file_type should
be either the string "image" or "file". If the file_type is "file", an image
representation can be loaded with the icon field, which contains the URL of a
icon file to use. The id parameter can be any value that the user wants, and is
often used to identify the file by its database ID as it is sent to the rename
and remove file URLs. Defaults to action 'files_on_server'.
xml.instruct! :xml, :version=>"1.0"
xml.instruct! :rss, :version=>"2.0"
xml.channel {
for file in (Dir.entries(@file_path) - [".",".."])
xml.file do
xml.name(file)
xml.size(number_to_human_size(File.size("#{@file_path}/#{file}")))
xml.bytes(File.size("#{@file_path}/#{file}"))
xml.url("http://#{request.host_with_port}/uploaded_files/#{file}")
xml.file_type(file_type(File.extname(file))
xml.id(file)
if File.extname(file)==".doc" or File.extname(file)==".pdf"
xml.icon("http://#{request.host_with_port}#{file_icon(File.extname(file))}")
end
end
end
}
==== 'renameFileURL'
This method is only used by Multi Bit Shift Advanced. URL that files should be
renamed with. The parameters old_file_name and id represent the file to be
renamed. The parameter new_file_name contains the name that the file should be
renamed to. The applicationToken is also sent to the url in the
parameter application_token.
When the upload was successful, Multi Bit Shift Advanced expects the updated
fileList XML to be returned.
On error, an xml error message formatted as
"ContentTitle" is exptected to
be returned. A popup error displaying the indicated error message to the
client.
Defaults to action 'rename_file'.
def rename_file
@file_path = "public/uploaded_files"
if File.exists?(@file_path + '/' + params['new_file_name'])
render(:xml => "Error!Cannot move the file, " +
"a file by that name currently exists.")
else
File.move(@file_path + '/' + params['old_file_name'], @file_path + '/' + params['new_file_name'])
render :action => "files_on_server"
end
end
=== Session Management
Multi Bit Shift and Multi Bit Shift Advanced both make use of the same session
management functionality. For all requests other than file upload, the current
browser session is sent to the server. The uploadURL, however, is not
sent the session. As such, we have a method that can request a token from the
server. The token is then sent with requests to the uploadURL so that the
client can be authenticated. In other words, the tokenRequestURL can
authenticate the user with their session, then genate a token. When a file is
uploaded, the server can watch for the token that was generated.
* 'tokenRequestURL' - URL that the token is requested from. The URL
expects a string representing the token to be returned. If this attribute is
left blank, no token request is made.
=== Query String Parameters
The applicationToken is a special token that is passed to the applet. It can be
used to further identify the user. For instance, using our helpers, the
applicationToken is used to identify the model that the files are associated
with.
Files must be passed into the Multi Bit Shift applet from the query string. The
parameters of interest are uploadedFileName#{number} and
uploadedFileSize#{number}. The number should start at 1, and go up
indefinitely. The uploadedFileName is the file name, and teh uploadedFileSize
is the size of the uploaded file in bytes.
=== Flash Applet Inclusion
When including the Multi Bit Shift or Multi Bit Shift Advanced flash applets on
pages, we recommend using our multi_bit_shift_flash helper. This helper will
automatically insert your query string parameters, and use javascript to write
the flash applet to the page. Parameters can be specified as hashes inside the
options parameter of the helper. An example call to include the Multi Bit Shift
applet follows:
multi_bit_shift_flash('uploadedFileName1'=>'smallImage.gif',
'uploadedFileSize1'=>'175','applicationToken'=>'214675-12231-182199')
An example call to include the Multi Bit Shift Advanced applet follows:
multi_bit_shift_flash({'mbs_version'=>'Advanced',
'flashCSS'=>'/flash/css/siu.swf', 'doneURL'=>url_for(:action=>'index'),
'fileListURL'=>url_for(:action=>'xml_file_listing'),
'fileLabel'=>'All Files', 'fileExtensions' => '*.*',
"maximumUploads" => "10", "maximumFileBytes" => "102400",
'mainPanelTitleText' => 'Multi Bit Shift Advanced Demo',
'maximumFileSizeAlert' => ' is larger than 1MB.'})
As you can see in the examples above, any of the query string parameters
expected by the applets can be passed to the applet by including it in the
options hash, where it is formatted and correctly presented.
=== Advanced Usage - Usage in Forms
==== Dependencies
To use the applets in forms, we have included some helper methods that will make
it easier to use. The UUID gem is required to use the plugin. We provide a
rake task to ease the installation of the gem. It can be installed by running
rake install_uuid from the root of the plugin directory. While it is
not required, we highly recommend using the high-quality open source plugin
file_column to handle the uploaded files. We provide a rake task for this
installation as well, which can be activated with the command rake
install_filecolumn from the root of the plugin directory.
==== Model/Migration Generation
The plugin requires a secondary table and model to store the actual files that
are associated with your primary model. The model and migration can be
generated by our script, with the command ruby script/generate
multi_bit_shift ClassName [command]. We recommend naming the class
MbsFile. Valid commands are [generate_model], [generate_migration],
[generate_validation_object], and [all]. We recommend generating all, with the
command ruby script/generate multi_bit_shift MbsFile all. In addition
to the model and the migration, this also generates the ValidateMbsFile model,
which is used to consolidate the number of places that validation settings are
entered. The model and migration that are generated are designed to be used
with the file_column plugin, and contain a file_name field that will represent
the uploaded file, and an associated_with column that will represent the main
model that the file is associated with. The associated_with column must be
named associated_with.
==== Model Configuration
The main model has to be prepared to have files associated with it. This is
done by creating a string column that can be named whatever you choose. We
generally suggest "files". This column will store a globally unique identifier
that will be used to locate files associated with the model. This behaviour is
automatic.
The file model, suggested to be MbsFile, also needs to be setup to accept file
uploads. If file_column is used, all that needs to be done is inserting the
line file_column :file_name into the MbsFile model, where 'file_name'
is the name of the column that will represent the file.
==== Automatic Validation
Validations can be configured in the ValidateMbsFile class. At the top of the
file, you will find a series of constant hashes which contain the validation
settings. By default, an example hash index called files exists. You can
modify the values associated with this index, or create additional index value
pairs. The automatic_mbs_validation method should be called from both
your main model and the model which represents your files. The call to the
method is the same in both classes, and will result in a series of validations
being performed before files and the main model are saved. An example call
follows:
automatic_mbs_validation ValidateMbsFile.new("files")
The ValidateMbsFile class can also be used to pass validation information to the
applets themselves through the multi_bit_shift_field helper. This will ensure
that the validations are performed both server and client side. The validation
object can be passed into the helper in the 'validation_object' index of the
options hash, as follows:
multi_bit_shift_field 'object_name', 'method', {"validation_object" => ValidateMbsFile.new("files")}
==== Multi Bit Shift Field Helper
The multi_bit_shift_field helper is desinged to be used in the same manner as
any other rails form field helper. The helper will insert a hidden field
containing the GUID corresponding to the main object, as well as the appropriate
flash applet. It is highly recommended that a validation object be included in
the options as it will assist in loading files and setting up client side
validation. Example usage for Multi Bit Shift is as follows:
multi_bit_shift_field 'object_name', 'method', {"validation_object" => ValidateMbsFile.new("files")}
Example usage for Multi Bit Shift Advanced is as follows:
multi_bit_shift_field 'object_name', 'method', {"validation_object" => ValidateMbsFile.new("files"), 'mbs_version' == 'Advanced'}
==== Server Side Methods Required
When Multi Bit Shift or Multi Bit Shift Advanced are used in forms, they must
still implement the methods from the Basic Requirements section above.
== Documentation Generation
To generate this documentation, use rake from the root of your app:
rake doc:plugins
Release documentation can be generated by changing to the plugin directory and
using the command rake release_docs. This command relies upon the
allison gem, which can be installed with the command gem install
allison.