The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

jQuery::File::Upload::Imager - Server-side solution for blueimp jQuery file upload plugin

SYNOPSIS

See also jQuery::File::Upload, from which this module was forked. The latter module requires Image::Magic, whereas this module requires Imager.

 use jQuery::File::Upload::Imager;

  #simplest implementation
  my $j_fu = jQuery::File::Upload::Imager->new;
  $j_fu->handle_request;
  $j_fu->print_response;

  #alternatively you can call $j_fu->handle_request(1) and this will call print_response for you.
  my $j_fu = jQuery::File::Upload::Imager->new;
  $j_fu->handle_request(1);

The above example is the simplest one possible, however it assumes a lot of defaults.

Assumptions

default upload directory

It is assumed that your files are being uploaded to the current directory of the script that's running, plus '/files'. So if your script is in /home/user/public_html, your files will be uploaded to /home/user/public_html/files.

default url

It is also assumed that the files will be hosted one directory above the running script, plus '/files'. So if the script is located at the url http://www.mydomain.com/upload.cgi, then all files will be assumed to be at the url http://www.mydomain.com/files/file_name.

default filename

Uploaded files are given a name at run time unless you specifically set the filename in the jQuery::File::Upload::Imager object.

same server upload

By default, jQuery::File::Upload::Imager also assumes that you're meaning to have the uploaded file uploaded to the same server that the script is running on. jQuery::File::Upload::Imager also has the ability to SCP files to remote servers, but this is not the default.

CGI environment

By default, jQuery::File::Upload::Imager assumes that the script is running in a regular CGI-type environment. However, jQuery::File::Upload::Imager also has the ability to work with Catalyst by being passed the context object.

all files

This implementation accepts all types of files.

A more complicated example

  use jQuery::File::Upload::Imager;

  my $j_fu = jQuery::File::Upload::Imager->new(
                scp => [{
                        user => 'user', #remote user
                        public_key => '/home/user/.ssh/id_rsa.pub',     #also possible to use password instead of keys
                        private_key => '/home/user/.ssh/id_rsa',
                        host => 'mydomain.com',
                        upload_dir => '/var/www/html/files', #directory that files will be uploaded to
                }],

                #user validation specifications
                max_file_size => 5242880, #max file size is 5mb
                min_file_size => 1,
                accept_file_types => ['image/jpeg','image/png','image/gif','text/html'], #uploads restricted to these filetypes
                max_width => 40000, #max width for images
                max_height => 50000, #max height for images
                min_width => 1,
                min_height => 1,
                max_number_of_files => 40, #maximum number of files we can have in our upload directory
          );


  $j_fu->handle_request;
  $j_fu->print_response;

Getting fancy

  use jQuery::File::Upload::Imager;

  my $j_fu = jQuery::File::Upload::Imager->new(
                        pre_get => sub {
                                my $j = shift; #jQuery::File::Upload::Imager object for current request
                                #any code in here will be executed before any get requests are handled
                                #jQuery File Upload makes Get request when the page first loads, so this
                                #can be useful for prefilling jQuery File Upload with files if you're using
                                #jQuery File upload with saved data to view/delete/upload more

                                #generate starting files for jQuery File Upload
                                $j->generate_output(
                                        [
                                                {
                                                        size => 500000,
                                                        filename =>     'my_image.jpeg',
                                                        image => 'y', #need to let jQuery::File::Upload::Imager know this is an image
                                                                      #or else thumbnails won't be deleted
                                                },
                                                {
                                                        size => 500000,
                                                        filename =>     'my_other_image.jpeg',
                                                        image => 'y',
                                                },
                                        ]
                                );

                                #The above makes assumptions yet again. It generates the url based on the defaults, unless
                                #you provide below the upload_url_base.
                        },
                        pre_delete => sub {
                                my $j = shift;

                                #here you can do something with the information in the params of the delete_url
                                #you can set your own meaningful delete_params (see below)
                                #NOTE: delete_urls always have the 'filename' param, so that might be enough for your needs
                                my $id = param->('id')

                                #DELETE FROM table WHERE id=$id
                                #etc.
                        },
                        post_post => sub {
                                my $j = shift;
                                #do some stuff here after post (image is uploaded)
                                #possibly save information about image in a database to keep track of it?
                                #you can call any methods now to get useful info:

                                #INSERT INTO table (name,is_image,width,height) VALUES($j->filename,$j->is_image,$j->final_width,$j->final_height)
                                #etc
                        },
                        delete_params => ['key1','val1','key2','val2'],
                                                            #this will add these key value pairs as
                                                            #params on the delete_url that is generated
                                                            #for each image. This could be useful if you
                                                            #kept track of these files in a database and wanted to
                                                            #delete them from the database when they are deleted.
                                                            #then delete_params could be ['id',unique_db_identifier]
                                                            #then you could check for the param 'id' in pre_delete
                                                            #and delete the file from your DB
                );


  #N.B. All of the above can also be set with the getter/setter methods

  $j_fu->handle_request(1); #when passed a one, will call print_response for you

DESCRIPTION

jQuery::File::Upload::Imager makes integrating server-side with the jQuery File Upload plugin simple. It provides many features, such as:

  1. the ability to SCP file uploads to remote servers

  2. the ability to provide your own functions to add to how each request is handled before the request and after the request

  3. options to validate the uploaded files server-side

  4. automatically generates thumbnails if the file is an image

  5. see below for everything you can do with jQuery::File::Upload::Imager

The location of the script should be where jQuery File Upload is told to upload to.

METHODS

Getters/Setters

new

Any of the below getters/setters can be passed into new as options.

  my $j_fu = jQuery::File::Upload::Imager->new(option=>val,option2=>val2,...);

upload_dir

  $j_fu->upload_dir('/home/user/public_html/files');

Sets the upload directory if saving files locally. Should not end with a slash. The default is the current directory of the running script with '/files' added to the end:

  /home/user/public_html/upload.cgi

yields:

  /home/user/public_html/files

When using jQuery::File::Upload::Imager under normal CGI, it should have no problem generating this default upload directory if that's what you want. However, if you are using Catalyst, depending on how you're running Catalyst (i.e. mod_perl, fastcgi, etc.) the generated default might be kind of strange. So if you are using Catalyst and you want to upload to the same server that jQuery::File::Upload::Imager is running on, it's best to just manually set this. Make sure that the user running your script can write to the directory you specify.

thumbnail_upload_dir

  $j_fu->thumbnail_upload_dir('/home/user/public_html/files/thumbs');

This can be used to set the upload directory form thumbnails. The default is "upload_dir". If you change this, that will make thumbnails have a different base url than "upload_url_base". Make sure to change "thumbnail_url_base" to match this accordingly. If you would like images and thumbnails to have the same name but just be in different directories, make sure you set "thumbnail_prefix" to ''. This should not end with a slash. Make sure that the user running your script can write to the directory you specify.

upload_url_base

  $j_fu->upload_url_base('http://www.mydomain.com/files');

Sets the url base for files. Should not end with a slash. The default is the current directory of the running script with '/files' added to the end:

  http://www.mydomain.com/upload.cgi

yields:

  http://www.mydomain.com/files

Which means that a file url would look like this:

  http://www.mydomain.com/files/file.txt

thumbnail_url_base

  $j_fu->thumbnail_url_base('http://www.mydomain.com/files/thumbs');

Sets the url base for thumbnails. Should not end with a slash. The default is "upload_url_base". Resulting thumbnail urls would look like:

  http://www.mydomain.com/files/thumbs/thumb_image.jpg

However, if "thumbnail_relative_url_base" is set, the default will be the current url with the thumbnail relative base at the end.

relative_url_path

  $j_fu->relative_url_path('/files');

This sets the relative url path for your files relative to the directory your script is currently running in. For example:

  http://www.mydomain.com/upload.cgi

yields:

  http://www.mydomain.com/files

and then all files will go after /files. The default for this is /files, which is why upload_url_base has the default /files at the end. If your location for the images is not relative, i.e. it is located at a different domain, then just set "upload_url_base" to get the url_base you want. There should not be a slash at the end.

thumbnail_relative_url_path

  $j_fu->thumbnail_relative_url_path('/files/thumbs');

This sets the thumbnail relative url path for your files relative to the directory your script is currently running in. For example:

  http://www.mydomain.com/upload.cgi

yields:

  http://www.mydomain.com/files/thumbs

and then all thumbnails will go after /files/thumbs. The default for this is nothing, so then the thumbnail_url will just fall back on whatever the value of "upload_url_base" is. If your location for thumbnail images is not relative, i.e. it is located at a different domain, then just set "thumbnail_url_base" to get the url_base you want. There should not be a slash at the end.

relative_to_host

  $j_fu->relative_to_host(1);

If set to 1, this will make "relative_url_path" and "thumbnail_relative_url_path" be relative to the host of the script url. For example:

  http://www.mydomain.com/folder/upload.cgi

With a "relative_url_path" '/files' would yield:

  http://www.mydomain.com/files

Whereas by default "relative_url_path" and "thumbnail_relative_url_path" are relative to the folder the upload script is running in.

If you use this option, make sure to set "upload_dir" (and/or "thumbnail_upload_dir" if necessary) since jQuery::File::Upload::Imager can no longer do a relative path for saving the file.

Default is undef.

field_name

  $j_fu->field_name('files[]');

This is the name of the jQuery File Uploader client side. The default is files[], as this is the jQuery File Upload plugin's default.

ctx

  $j_fu->ctx($c);

This is meant to set the Catalyst context object if you are using this plugin with Catalyst. The default is to not use this.

cgi

  $j_fu->cgi(CGI->new);

This should be used mostly internally by jQuery::File::Upload::Imager (assuming you haven't passed in ctx). It is just the CGI object that the module uses, however if you already have one you could pass it in.

should_delete

  $j_fu->should_delete(1)

This is used to decide whether to actually delete the files when jQuery::File::Upload::Imager receives a DELETE request. The default is to delete, however this could be useful if you wanted to maybe just mark the field as deleted in your database (using "pre_delete") and then actually physically remove it with your own clean up script later. The benefit to this could be that if you are SCPing the files to a remote server, perhaps issuing the remote commands to delete these files is something that seems to costly to you.

scp

  $j_fu->scp([{
                        host => 'media.mydomain.com',
                        user => 'user',
                        public_key => '/home/user/.ssh/id_rsa.pub',
                        private_key => '/home/user/.ssh/id_rsa',
                        password => 'pass', #if keys are present, you do not need password
                        upload_dir => '/my/remote/dir',
                }]);

This method takes in an arrayref of hashrefs, where each hashref is a remote host you would like to SCP the files to. SCPing the uploaded files to remote hosts could be useful if say you hosted your images on a different server than the one doing the uploading.

SCP OPTIONS

  • host (REQUIRED) - the remote host you want to scp the files to, i.e. 127.0.0.1 or media.mydomain.com

  • user (REQUIRED) - used to identify the user to remote server

  • public_key & private_key - used to make secure connection. Not needed if password is given.

  • password - used along with user to authenticate with remote server. Not needed if keys are supplied.

  • upload_dir (REQUIRED) - the directory you want to scp to on the remote server. Should not end with a slash

  • thumbnail_upload_dir - Will default to upload_dir. You only need to provide this if your thumbnails are stored in a different directory than regular images. Should not end with a slash

You can check Net::SSH2 for more information on connecting to the remote server.

max_file_size

  $j_fu->max_file_size(1024);

Sets the max file size in bytes. By default there is no max file size.

min_file_size

  $j_fu->min_file_size(1);

Sets the minimum file size in bytes. Default minimum is 1 byte. to disable a minimum file size, you can set this to undef or 0.

accept_file_types

  $j_fu->accept_file_types(['image/jpeg','image/png','image/gif','text/html']);

Sets what file types are allowed to be uploaded. By default, all file types are allowed. File types should be in the format of the Content-Type header sent on requests.

require_image

  $j_fu->require_image(1);

If set to 1, it requires that all uploads must be an image. Setting this is equivalent to calling:

  $j_fu->accept_file_types(['image/jpeg','image/jpg','image/png','image/gif']);

Default is undef.

delete_params

  $j_fu->delete_params(['key1','val1','key2','val2']);

Sets the keys and values of the params added to the delete_url. This can be useful when used with "pre_delete", because if you are keeping track of these files in a database, you can add unique identifiers to the params so that in "pre_delete" you can get these unique identifiers and use them to remove or edit the file in the databse. By default filename will also be a param unless you set the delete_url manually.

delete_url

  $j_fu->delete_url('http://www.mydomain.com/upload.cgi?filename=file.jpg');

This can be used to set the delete_url that will be requested when a user deletes a file. However, it is recommended that you do not set this manually and rather use "delete_params" if you want to add your own params to the delete_url.

thumbnail_width

  $j_fu->thumbnail_width(80);

This sets the width for the thumbnail that will be created if the file is an image. Default is 80.

thumbnail_height

  $j_fu->thumbnail_height(80);

This sets the height for the thumbnail that will be created if the file is an image. Default is 80.

tumbnail_quality

  $j_fu->thumbnail_quality(70);

This sets the quality of the generated thumbnail. Default is 70 and it can be on a scale of 0-100. See Image::Magick for more information.

thumbnail_quality

  $j_fu->thumbnail_quality(70);

This sets the quality of the thumbnail image. Default is 70 and it can be on a scale of 0-100. See Image::Magick for more information.

thumbnail_format

  $j_fu->thumbnail_format('jpg');

Sets the format for the generated thumbnail. Can be jpg, png, or gif. See Image::Magick for more information. Defaults to jpg.

thumbnail_density

  $j_fu->thumbnail_density('80x80');

Sets the density for the generated thumbnail. Default is width x height. See Image::Magick for more information.

thumbnail_prefix

  $j_fu->thumbnail_prefix('thumb_');

Added before the image filename to create the thumbnail unique filename. Default is 'thumb_'.

thumbnail_postfix

  $j_fu->thumbnail_postfix('_thumb');

Added after the image filename to create the thumbnail unique filename. Default is ''.

thumbnail_final_width

  my $final_width = $j_fu->thumbnail_final_width;

Because the thumbnails are scaled proportionally, the thumbnail width may not be what you orignally suggested. This gets you the final width.

thumbnail_final_height

  my $final_height = $j_fu->thumbnail_final_height;

Because the thumbnails are scaled proportionally, the thumbnail height may not be what you orignally suggested. This gets you the final height.

quality

  $j_fu->quality(70);

This sets the quality of the uploaded image. Default is 70 and it can be on a scale of 0-100. See Image::Magick for more information.

format

  $j_fu->format('jpg');

Sets the format for the generated thumbnail. Can be jpg,png, or gif. See Image::Magick for more information. Defaults to jpg.

final_width

  my $final_width = $j_fu->final_width;

Returns the final width of the uploaded image.

final_height

  my $final_height = $j_fu->final_height;

Returns the final height of the uploaded image.

max_width

  $j_fu->max_width(10000);

Sets the maximum width of uploaded images. Will return an error to browser if not valid. Default is any width.

max_height

  $j_fu->max_height(10000);

Sets the maximum height of uploaded images. Will return an error to browser if not valid. Default is any height.

min_width

  $j_fu->min_width(10000);

Sets the minimum width of uploaded images. Will return an error to browser if not valid. Default is 1.

min_height

  $j_fu->min_height(10000);

Sets the minimum height of uploaded images. Will return an error to browser if not valid. Default is 1.

max_number_of_files

  $j_fu->max_number_of_files(20);

Sets the maximum number of files the upload directory can contain. Returns an error to the browser if number is reached. Default is any number of files. If you have listed multiple remote directories, the maximum file count out of all of these directories is what will be used.

filename

  my $filename = $j_fu->filename;

Returns the resulting filename after processing the request.

  $j_fu->filename('my_name.txt');

You can also set the filename to use for this request before you call handle_request. However, unless you're sure that you are going to give the file a unique name, you should just let jQuery::File::Upload::Imager generate the filename. Please note that if you choose your own filename, you do have to manually set "thumbnail_filename"

absolute_filename

  my $absolute_filename = $j_fu->absolute_filename;

Returns the absolute filename of the file on the server. You can also set this manually if you would like, or jQuery::File::Upload::Imager will generate it for you.

thumbnail_filename

  $j_fu->filename('my_name.txt');

You can also set the thumbnail_filename to use for this request before you call "handle_request". However, unless you're sure that you are going to give the file a unique name, you should just let jQuery::File::Upload::Imager generate the filename.

absolute_thumbnail_filename

  my $absolute_filename = $j_fu->absolute_thumbnail_filename;

Returns the absolute filename of the thumbnail image on the server. You can also set this manually if you would like, or jQuery::File::Upload::Imager will generate it for you.

client_filename

  my $client_filename = $j_fu->client_filename;

Returns the filename of the file as it was named by the user.

show_client_filename

  $j_fu->show_client_filename(1);

This can be used to set whether jQuery::File::Upload::Imager shows the user the name of the file as it looked when they uploaded, or the new name of the file. When set to true, the user will see the file as it was named on their computer. The default is true, and this is recommended because typically the user's filename will look better than the unique one that jQuery::File::Upload::Imager generates for you.

use_client_filename

  $j_fu->use_client_filename(0);

If this is set to true, jQuery::File::Upload::Imager will use the user's name for the file when saving it. However, this is not recommended because the user could have two files named the same thing that could overwrite one another, and same scenario between two different users. It is best to let jQuery::File::Upload::Imager generate the filenames to save with because these are much more likely to be unique. Another reason not to use client filenames is that it is possible that they could have invalid characters in them such as spaces which will prevent a url from loading.

filename_salt

  $j_fu->filename_salt('_i_love_the_circus');

Anything added here will be appended to the end of the filename. This is meant to be used if you want to guarantee uniqueness of image names, i.e. you could use a user id at the end to greatly lessen the chance of duplicate filenames. Default is nothing.

tmp_dir

  $j_fu->tmp_dir('/tmp');

The provided directory will be used to store temporary files such as images. Make sure that the user the script is running under has permission to create and write to files in the tmp_dir. Also, there should be no slash at the end. Default is /tmp.

script_url

  $j_fu->script_url('http://www.mydomain.com/upload.cgi');

This can be used to set the url of the script that jQuery::File::Upload::Imager is running under. jQuery::File::Upload::Imager then uses this value to generate other parts of the output. jQuery::File::Upload::Imager in most cases is able to figure this out on its own, however if you are experiencing issues with things such as url generation, try setting this manually.

data

  $j_fu->data({
            dbh => $dbh,
            my_var = $var,
            arr = [],
            self => $self, #maybe useful for Catalyst
        });

This method can be populated with whatever you like. Its purpose is if you need to get access to other data in one of your "PRE/POST REQUEST METHODS". This way you can access any outside data you need by calling "data" on the jQuery::File::Upload::Imager object that you are passed. However, keep in mind that if you are using Catalyst, you will have access to the context object via the jQuery::File::Upload::Imager object that is passed in, and this would be an equally good place to store/retrieve data that you need.

JUST GETTERS

output

  my $output = $j_fu->output;

Returns the JSON output that will be printed to the browser. Unless you really feel you need the JSON, it's usually just easier to call "print_response" as this prints out the header and the JSON for you (or alternatively call "handle_response" and pass it a 1 so that it will call "print_response" for you.

url

  my $file_url = $j_fu->url;

This returns the resulting url of the file.

thumbnail_url

  my $thumbnail_url = $j_fu->thumbnail_url;

This returns the resulting thumbnail url of the image.

is_image

  my $is_image = $j_fu->is_image;

Returns whether or not the uploaded file was an image. This should be called after "handle_request" or in "post_post".

OTHER METHODS

  $j_fu->print_response;

Should be called after "handle_request". Prints out header and JSON back to browser. Called for convenience by "handle_request" if "handle_request" is passed a 1.

handle_request

  $j_fu->handle_request;

Called to handle one of 'GET','POST', or 'DELETE' requests. If passed a 1, will also call "print_response" after it's finished.

generate_output

  $j_fu->generate_output([{
                        image => 'y', #or 'n'
                        filename => 'my_cool_pic.jpg',
                        size => 1024,
                  }]);

This should be used in conjuction with "pre_get" to populate jQuery File Upload with files on page load. It takes in an arrayref of hashrefs, where each hashref is a file. After this method is called, you will need to call "print_response" or "handle_request" with a 1 to print out the JSON.

GENERATE_OUTPUT OPTIONS

  • filename (REQUIRED) - name of the file

  • size (REQUIRED) - size in bytes

  • image - 'y' or 'n'. Necessary if file is image and you would like thumbnail to be deleted with file. Also, needed if you want thumbnail to be displayed by jQuery File Upload

  • name - name that will be displayed to client as the filename. If not provided, defaults to filename. Can be used well with client_filename to make filename's look prettier client-side.

  • thumbnail_filename - filename for thumbnail. jQuery::File::Upload::Imager will generate the thumbnail_filename based on the filename and other factors (such as "upload_url_base") if you don't set this.

  • url - url used for file. If not provided, will be generated with filename and other defaults.

  • thumbnail_url - url used for thumbnail. If not provided, will be generated with other defaults.

  • delete_url - url that will be called by jQuery File Upload to delete the file. It's better to just let jQuery::File::Upload::Imager generate this and use "delete_params" if you want to set your own parameters for the delete url.

  • delete_params - The format of this is just like "delete_params". It takes [key,value] pairs. Any values here will be added in addition to any global "delete_params" that you set.

  • error - can be used to supply an error for a file (although I don't really know why you would use this...)

Note that jQuery::File::Upload::Imager will generate urls and such based upon things given here (like filename) and other options such as "upload_url_base".

PRE/POST REQUEST METHODS

N.B. The following functions are all passed a jQuery::File::Upload::Imager object. And they can be passed into "new" as options.

Also, note that since all of these user-defined methods are passed the jQuery::File::Upload::Imager object, if you are using Catalyst you can just call the "ctx" method to get anything stored via your context object. For Catalyst users, this makes this a practical (and possibly better) alternative to the provided "data" method.

pre_delete

  $j_fu->pre_delete(sub { my $j_fu = shift });

or

  $j_fu->pre_delete(\&mysub);

pre_delete will be called before a delete request is handled. This can be useful if you want to mark a file as deleted in your database. Also, you can use this along with "delete_params" to set unique identifiers (such as an id for the file or the primary key) so that you can find the file in your database easier to perform whatever operations you want to on it. Note: This will be called even if "should_delete" is set to false.

post_delete

  $j_fu->post_delete(sub { my $j_fu = shift });

or

  $j_fu->post_delete(\&mysub);

post_delete will be called after a delete request is handled. Note: This will not be called if "should_delete" is set to false.

pre_post

  $j_fu->pre_post(sub { my $j_fu = shift });

or

  $j_fu->pre_post(\&mysub);

pre_post will be called before a post request is handled. POST requests are what happen when jQuery File Upload uploads your file.

post_post

  $j_fu->post_post(sub { my $j_fu = shift });

or

  $j_fu->post_post(\&mysub);

post_post will be called after a post request is handled. This can be useful if you want to keep track of the file that was just uploaded by recording it in a database. You can use the jQuery::File::Upload::Imager object that is passed in to get information about the file that you would like to store in the databse. Later on you can use this stored information about the files to prepopulate a jQuery File Upload form with files you already have by preloading the form by using "pre_get".

pre_get

  $j_fu->pre_get(sub { my $j_fu = shift });

or

  $j_fu->pre_get(\&mysub);

pre_get will be called before a get request is handled. Get requests happen on page load to see if there are any files to prepopulate the form with. This method can be useful to prepopulate the jQuery File Upload form by combining saved information about the files you want to load and using "generate_output" to prepare the output that you would like to send to the jQuery File Upload form.

post_get

  $j_fu->post_get(sub { my $j_fu = shift });

or

  $j_fu->post_get(\&mysub);

post_get will be called after a get request is handled.

EXPORT

None by default.

FAQ

General comments

I (Ron) have made the minimal number of patches to the code for jQuery::File::Upload requried to get it to work.

I have also made a few patches to the POD, on the assumption more-or-less everything applies to this fork of the code. This FAQ is my main addition to the POD.

Version numbers

I (Ron) am using V 8.2.1 of https://blueimp.net/'s jQuery plugin, and V 0.16 of Adam Hopkins' Perl module jQuery::File::Upload.

Handling the file suffixes *.vcf and *.txt

jQuery submits Ajax calls with a file type of 'text/directory' when the file suffix is *.vcf, on the assumption it is a RFC 2426 - vCard MIME Directory Profile-style file.

Hence, in the config file (or wherever) you specify "accept_file_types" for the call to new(), be aware you need to set "accept_file_types" to be 'text/directory' when the file suffix is *.vcf.

Alternately, if you upload a file with the *.txt suffix, jQuery uses a file type of 'text/plain'.

Lastly, recall "accept_file_types" takes an arrayref of strings, not just a string.

Temporary storage 'v' permanent storage

The code basically assumes you're uploading images with optional thumbnails, which is a very common use case. This in turn assumes all files are to be saved permanently on the server.

This does mean that in the call to new() you must specify a value for "upload_dir" even if you never intend to save the file.

I (Ron) use it to upload exports from the address books of email clients. In these cases, the uploaded file is processed and then discarded. Permanent storage is not relevant.

Also, in your call to new(), ensure you set upload_dir and tmp_dir to different directories.

One way to handle this is to use File::Temp to generate a dir name for tmp_dir.

        # The EXLOCK option is for BSD-based systems.

        my($dir_name) = File::Temp::newdir('temp.XXXX', CLEANUP => 1, EXLOCK => 0, TMPDIR => 1);

The code uses $ENV{SCRIPT_URI} but web servers set $ENV{SCRIPT_NAME}

Yes. This is a bug unless there is some web server somewhere which sets $ENV{SCRIPT_URI}.

I (Ron) did not examine this code yet.

The code assumes you have set script_url

Yes. Just use something suitable in the call to new().

Leaving it unset generates uninitialized warnings.

The code assumes you have set delete_url

Yes. Just use something harmless in the call to new().

Leaving it unset generates uninitialized warnings.

Calling sub handle_request() which calls sub _clear()

In jQuery::File::Upload, sub _clear() is called at the start of "handle_request", but this zaps parameters to new() before they can be used.

In this module, jQuery::File::Upload::Imager, I have moved this call to the end of "handle_request".

Calling sub handle_request() which calls sub _post() which calls sub _save()

In jQuery::File::Upload, the output file handle is not closed, meaning the ouput file contains 0 bytes.

In this module, jQuery::File::Upload::Imager, I call close.

There is commented-out code in sub _save_cloud() which writes to the same file handle. I have not examined that code nor have I un-commented it.

Catalyst Performance - Persistent jQuery::File::Upload::Imager

A jQuery::File::Upload::Imager object shouldn't be too expensive to create, however if you'd like to only create the object once you could create it as an Moose attribute to the class:

  use jQuery::File::Upload::Imager;
  has 'j_uf' => (isa => 'jQuery::File::Upload::Imager', is => 'rw',
                  lazy => 0, default => sub { jQuery::File::Upload::Imager->new } );

However, if you do this it is possible that you could run into issues with values of the jQuery::File::Upload::Imager object that were not cleared messing with the current request. The _clear method is called before every "handle_request" which clears the values of the jQuery::File::Upload::Imager object, but it's possible I may have missed something. You did! See the "FAQ".

SEE ALSO

AUTHOR

Adam Hopkins, <srchulo@cpan.org<gt>

Ron Savage <ron@savage.net.au> has patched jQuery::File::Upload V 0.16 to use Imager rather than Image::Magick, on 2013-05-23. See the "FAQ" for details.

Bugs

I haven't tested this too thoroughly beyond my needs, so it is possible that I have missed something. If I have, please feel free to submit a bug to the bug tracker, and you can send me an email letting me know that you submitted a bug if you want me to see it sooner :)

COPYRIGHT AND LICENSE

Copyright (C) 2013 by Adam Hopkins

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.