You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Qunhuan Mei <qm...@qm18.wanadoo.co.uk> on 2009/06/04 10:07:03 UTC

Ajax file upload + RE: About the "struts.multipart.saveDir" for file upload

Hi Wes, 

Struts’ ajax file upload would be very interesting to me since I have
implemented jQuery (http://www.phpletter.com/Our-Projects/AjaxFileUpload/)
and Struts for ajax file upload in my application and had one or two
problem(s).

FYI: My use case is to upload a file, together with utf8 encoded caption.
The problem I had is utf8 encoded caption needs to be sent via HTTP POST, it
won’t work with HTTP get. But the jQuery arrangement is sending file in POST
while sending caption in Get. So what I did is to send caption and file in
two POSTs which cause other complications. Later the author (Øyvind Saltvik
oyvind.saltvik@gmail.com) sent me the following code contributed by
(Prokofiev Nikolay nprokofiev@gmail.com) which added the parameter POSTing
(e.g. caption) to jQuery’s file upload. 

$.ajaxFileUpload
        (
            {
                url:document.location+'&ajax=true', 
                secureuri:false,
                fileElementId:'fileToUpload',
                data: {foo: 'ghffgh', bar: 'fghfhgg'},
                dataType: 'json',
                success: function (data, status)
                {                    
                    if(typeof(data.error) != 'undefined')
                    {
                        if(data.error != '')
                        {
                            alert(data.error);
                        }else
                        {
                            alert(data.msg);
                        }
                    } 
                },
                error: function (data, status, e)
                { 
                    alert(e);
                }
            }
        )

here is the script:
jQuery.extend({
    createUploadIframe: function(id, uri)
    {
            //create frame
            var frameId = 'jUploadFrame' + id;
            
            if(window.ActiveXObject) {
                var io = document.createElement('<iframe id="' + frameId +
'" name="' + frameId + '" />');
                if(typeof uri== 'boolean'){
                    io.src = 'javascript:false';
                }
                else if(typeof uri== 'string'){
                    io.src = uri;
                }
            }
            else {
                var io = document.createElement('iframe');
                io.id = frameId;
                io.name = frameId;
            }
            io.style.position = 'absolute';
            io.style.top = '-1000px';
            io.style.left = '-1000px';

            document.body.appendChild(io);

            return io            
    },
    createUploadForm: function(id, fileElementId, postData)
    {
        //create form    
        var formId = 'jUploadForm' + id;
        var fileId = 'jUploadFile' + id;
        var form = $('<form  action="" method="POST" name="' + formId + '"
id="' + formId + '" enctype="multipart/form-data"></form>');    
        var oldElement = $('#' + fileElementId);
        var newElement = $(oldElement).clone();
        $(oldElement).attr('id', fileId);
        $(oldElement).before(newElement);
        $(oldElement).appendTo(form);
        try
        {
            for(param in postData)
            {
                  var   input = document.createElement('input');
                      input.setAttribute('name', param);
                      input.setAttribute('value', postData[param]);
                      $(input).appendTo(form);
            }
        }
        catch(e) {}
        //set attributes
        $(form).css('position', 'absolute');
        $(form).css('top', '-1200px');
        $(form).css('left', '-1200px');
        $(form).appendTo('body');        
        return form;
    },
    ajaxFileUpload: function(s) {
        // TODO introduce global settings, allowing the client to modify
them for all requests, not only timeout        
        s = jQuery.extend({}, jQuery.ajaxSettings, s);
        var id = new Date().getTime()        
        var form = jQuery.createUploadForm(id, s.fileElementId, s.data);
        var io = jQuery.createUploadIframe(id, s.secureuri);
        var frameId = 'jUploadFrame' + id;
        var formId = 'jUploadForm' + id;        
        // Watch for a new set of requests
        if ( s.global && ! jQuery.active++ )
        {
            jQuery.event.trigger( "ajaxStart" );
        }            
        var requestDone = false;
        // Create the request object
        var xml = {}   
        if ( s.global )
            jQuery.event.trigger("ajaxSend", [xml, s]);
        // Wait for a response to come back
        var uploadCallback = function(isTimeout)
        {            
            var io = document.getElementById(frameId);
            try 
            {                
                if(io.contentWindow)
                {
                     xml.responseText =
io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null
;
                     xml.responseXML =
io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:
io.contentWindow.document;
                     
                }else if(io.contentDocument)
                {
                     xml.responseText =
io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:
null;
                    xml.responseXML =
io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocum
ent:io.contentDocument.document;
                }                        
            }catch(e)
            {
                jQuery.handleError(s, xml, null, e);
            }
            if ( xml || isTimeout == "timeout") 
            {                
                requestDone = true;
                var status;
                try {
                    status = isTimeout != "timeout" ? "success" : "error";
                    // Make sure that the request was successful or
notmodified
                    if ( status != "error" )
                    {
                        // process the data (runs the xml through httpData
regardless of callback)
                        var data = jQuery.uploadHttpData( xml, s.dataType );

                        // If a local callback was specified, fire it and
pass it the data
                        if ( s.success )
                            s.success( data, status );
    
                        // Fire the global callback
                        if( s.global )
                            jQuery.event.trigger( "ajaxSuccess", [xml, s] );
                    } else
                        jQuery.handleError(s, xml, status);
                } catch(e) 
                {
                    status = "error";
                    jQuery.handleError(s, xml, status, e);
                }

                // The request was completed
                if( s.global )
                    jQuery.event.trigger( "ajaxComplete", [xml, s] );

                // Handle the global AJAX counter
                if ( s.global && ! --jQuery.active )
                    jQuery.event.trigger( "ajaxStop" );

                // Process result
                if ( s.complete )
                    s.complete(xml, status);

                jQuery(io).unbind()

                setTimeout(function()
                                    {    try 
                                        {
                                            $(io).remove();
                                            $(form).remove();    
                                            
                                        } catch(e) 
                                        {
                                            jQuery.handleError(s, xml, null,
e);
                                        }


                                    }, 100)

                xml = null

            }
        }
        // Timeout checker
        if ( s.timeout > 0 ) 
        {
            setTimeout(function(){
                // Check to see if the request is still happening
                if( !requestDone ) uploadCallback( "timeout" );
            }, s.timeout);
        }
        try 
        {
           // var io = $('#' + frameId);
            var form = $('#' + formId);
            $(form).attr('action', s.url);
            $(form).attr('method', 'POST');
            $(form).attr('target', frameId);
            if(form.encoding)
            {
                form.encoding = 'multipart/form-data';                
            }
            else
            {                
                form.enctype = 'multipart/form-data';
            }            
            $(form).submit();

        } catch(e) 
        {            
            jQuery.handleError(s, xml, null, e);
        }
        if(window.attachEvent){
            document.getElementById(frameId).attachEvent('onload',
uploadCallback);
        }
        else{
            document.getElementById(frameId).addEventListener('load',
uploadCallback, false);
        }         
        return {abort: function () {}};    

    },

    uploadHttpData: function( r, type ) {
        var data = !type;
        data = type == "xml" || data ? r.responseXML : r.responseText;
        // If the type is "script", eval it in global context
        if ( type == "script" )
            jQuery.globalEval( data );
        // Get the JavaScript object, if JSON is used.
        if ( type == "json" )
            eval( "data = " + data );
        // evaluate scripts within html
        if ( type == "html" )
            jQuery("<div>").html(data).evalScripts();
            //alert($('param',
data).each(function(){alert($(this).attr('value'));}));
        return data;
    }
})

But during my tesing, the code appears to run ok only in IE (IE 7). It
failed on Firefox (3.0.10), Safari (3.2.1) and Chrome (1.0.154.65), with
simply no request received from the server after “jQuery(form).submit();”
and no exception thrown or captured either. I reported the problem back but
so far no reply (I am not a Javascript expert). 

Hope your ajax file upload approach will also handle UTF8 encoded caption –
I certainly would do some testing when your code is ready
The other issue in my mind about file upload is if “multi-file upload in one
submit” could be achieved. I saw it in Flash version where user selects
multiple files using Window’s file selection while keeping control key down.
I suppose this ability would bring Struts’ file upload to the next level.

Kind regards,

Qunhuan

-----Original Message-----
From: Wes Wannemacher [mailto:wesw@wantii.com] 
Sent: 03 June 2009 22:03
To: Struts Users Mailing List
Subject: Re: About the "struts.multipart.saveDir" for file upload


I'll check it out, I just wanted to improve what we had because it's
currently impossible to do things like an AJAX upload with accurate
progress bar. After I get the plugin (1.0-SNAPSHOT, which is the maven
way of saying beta) committed to the sandbox, I'll whip up a quick
example of how to do an AJAX w/progress bar using struts.

-Wes

On Wed, Jun 3, 2009 at 5:00 PM, Andy <an...@hotmail.com> wrote:
>
> That's great Wes.  I am using the file upload but only sparingly (and
hacked) due to some existing glitches.
>
>
>
> I read how the Stripes framework does file upload:
 http://www.stripesframework.org/display/stripes/File+Uploads
>
>
>
> Thought you might find it interesting/useful..
>
>
>
> Andy
>
>
>
>> Date: Wed, 3 Jun 2009 16:48:56 -0400
>> Subject: Re: About the "struts.multipart.saveDir" for file upload
>> From: wesw@wantii.com
>> To: user@struts.apache.org
>>
>> I don't know if I would suggest it, but you might be able to call -
>>
>> Dispatcher.getInstance().setMultipartSaveDir(String path)
>>
>> Now, I can't remember if there is one dispatcher per thread, so you
>> might have to call it in an interceptor.
>>
>> However, I would strongly suggest against doing that.
>>
>> I am working on an enhanced file upload plugin right now and will
>> probably commit it to the sandbox by tomorrow. The problem with the
>> stock file upload capability is that the FileItemFactory and
>> FileUpload objects are not available to be overridden, and hardly any
>> configuration is made visible. So, I've got a new
>> JakartaMultiPartRequest class I'll have out by tomorrow.
>>
>> -Wes
>>
>> On Wed, Jun 3, 2009 at 4:37 PM, Andy <an...@hotmail.com> wrote:
>> >
>> > It defaults but I think he's wondering how he can set the dir
programatically.
>> >
>> >
>> >
>> >> Date: Wed, 3 Jun 2009 15:35:33 -0500
>> >> Subject: Re: About the "struts.multipart.saveDir" for file upload
>> >> From: burtonrhodes@gmail.com
>> >> To: user@struts.apache.org
>> >>
>> >> I wasn't aware that it was required. If you don't specify doesn't it
>> >> default to the 'work' directory?
>> >>
>> >> On 6/3/09, Qunhuan Mei <qm...@qm18.wanadoo.co.uk> wrote:
>> >> >
>> >> > Hi,
>> >> >
>> >> > When implementing file upload, it is required to specify an absolute
>> >> > directory in struts.xml such as following:
>> >> >
>> >> > <constant name="struts.multipart.saveDir"
value="C:/fileUploadTempDir"
>> >> > />
>> >> >
>> >> > But this might be difficult to achieve, say when the project war is
deployed
>> >> > in a external shared server and we do not have much idea about the
directory
>> >> > structure of the target server machine.
>> >> >
>> >> > I was wondering if there is any recommended way to handle this
issue.
>> >> >
>> >> > Ideally I would like to specify the directory in java code where I
can
>> >> > detect the current working directory and specify the saveDir
accordingly. Is
>> >> > this possible?
>> >> >
>> >> > Many thanks in advance,
>> >> >
>> >> > Qunhuan
>> >> >
>> >> >
>> >> >
>> >> >
>> >> >
---------------------------------------------------------------------
>> >> > To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
>> >> > For additional commands, e-mail: user-help@struts.apache.org
>> >> >
>> >> >
>> >>
>> >> --
>> >> Sent from my mobile device
>> >>
>> >> ---------------------------------------------------------------------
>> >> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
>> >> For additional commands, e-mail: user-help@struts.apache.org
>> >>
>> >
>> > _________________________________________________________________
>> > Windows Live™: Keep your life in sync.
>> >
http://windowslive.com/explore?ocid=TXT_TAGLM_WL_BR_life_in_synch_062009
>>
>>
>>
>> --
>> Wes Wannemacher
>> Author - Struts 2 In Practice
>> Includes coverage of Struts 2.1, Spring, JPA, JQuery, Sitemesh and more
>> http://www.manning.com/wannemacher
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
>> For additional commands, e-mail: user-help@struts.apache.org
>>
>
> _________________________________________________________________
> Insert movie times and more without leaving Hotmail®.
>
http://windowslive.com/Tutorial/Hotmail/QuickAdd?ocid=TXT_TAGLM_WL_HM_Tutori
al_QuickAdd_062009



-- 
Wes Wannemacher
Author - Struts 2 In Practice
Includes coverage of Struts 2.1, Spring, JPA, JQuery, Sitemesh and more
http://www.manning.com/wannemacher

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org





---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


RE: Ajax file upload + RE: About the "struts.multipart.saveDir" for file upload

Posted by Qunhuan Mei <qm...@qm18.wanadoo.co.uk>.
Ok Wes, I'll wait for your code to be ready. You guys hard work make us
developers' work easier. Many thanks for that! Qunhuan

-----Original Message-----
From: Wes Wannemacher [mailto:wesw@wantii.com] 
Sent: 04 June 2009 13:38
To: Struts Users Mailing List
Subject: Re: Ajax file upload + RE: About the "struts.multipart.saveDir" for
file upload


Really, I haven't gotten that far yet, I am only working to improve
the integration with Jakarta FileUpload. JFU is quite capable and
mature, but I figured the first step would be to expose more
functionality since there were a few JIRAs related to people asking
for more than what is currently offered.

I committed a partially complete plugin to the sandbox yesterday
before I left my office, but I still need to glue it together with
configuration, etc. (and work out a bug I realized I had in the middle
of the night last night). Once I get the plugin to an installable
state, you can check it out. I figure the first step is to make the
plugin work, then the next step is building an example UI. I am not
sure how I am going to build the example UI, but JQuery is probably
the most likely candidate for me.

As far as selecting multiple files with Ctrl-Click, I'm not sure if
that is possible... Not from a struts/jquery perspective, but I don't
know if the browser will let you do that. I think Flash may be the
only option (or a java applet or something, but flash is more likely),
so we can come back to that later.

-Wes

On Thu, Jun 4, 2009 at 4:07 AM, Qunhuan Mei <qm...@qm18.wanadoo.co.uk> wrote:
> Hi Wes,
>
> Struts’ ajax file upload would be very interesting to me since I have
> implemented jQuery (http://www.phpletter.com/Our-Projects/AjaxFileUpload/)
> and Struts for ajax file upload in my application and had one or two
> problem(s).
>
> FYI: My use case is to upload a file, together with utf8 encoded caption.
> The problem I had is utf8 encoded caption needs to be sent via HTTP POST,
it
> won’t work with HTTP get. But the jQuery arrangement is sending file in
POST
> while sending caption in Get. So what I did is to send caption and file in
> two POSTs which cause other complications. Later the author (Øyvind
Saltvik
> oyvind.saltvik@gmail.com) sent me the following code contributed by
> (Prokofiev Nikolay nprokofiev@gmail.com) which added the parameter POSTing
> (e.g. caption) to jQuery’s file upload.
>
> $.ajaxFileUpload
>        (
>            {
>                url:document.location+'&ajax=true',
>                secureuri:false,
>                fileElementId:'fileToUpload',
>                data: {foo: 'ghffgh', bar: 'fghfhgg'},
>                dataType: 'json',
>                success: function (data, status)
>                {
>                    if(typeof(data.error) != 'undefined')
>                    {
>                        if(data.error != '')
>                        {
>                            alert(data.error);
>                        }else
>                        {
>                            alert(data.msg);
>                        }
>                    }
>                },
>                error: function (data, status, e)
>                {
>                    alert(e);
>                }
>            }
>        )
>
> here is the script:
> jQuery.extend({
>    createUploadIframe: function(id, uri)
>    {
>            //create frame
>            var frameId = 'jUploadFrame' + id;
>
>            if(window.ActiveXObject) {
>                var io = document.createElement('<iframe id="' + frameId +
> '" name="' + frameId + '" />');
>                if(typeof uri== 'boolean'){
>                    io.src = 'javascript:false';
>                }
>                else if(typeof uri== 'string'){
>                    io.src = uri;
>                }
>            }
>            else {
>                var io = document.createElement('iframe');
>                io.id = frameId;
>                io.name = frameId;
>            }
>            io.style.position = 'absolute';
>            io.style.top = '-1000px';
>            io.style.left = '-1000px';
>
>            document.body.appendChild(io);
>
>            return io
>    },
>    createUploadForm: function(id, fileElementId, postData)
>    {
>        //create form
>        var formId = 'jUploadForm' + id;
>        var fileId = 'jUploadFile' + id;
>        var form = $('<form  action="" method="POST" name="' + formId + '"
> id="' + formId + '" enctype="multipart/form-data"></form>');
>        var oldElement = $('#' + fileElementId);
>        var newElement = $(oldElement).clone();
>        $(oldElement).attr('id', fileId);
>        $(oldElement).before(newElement);
>        $(oldElement).appendTo(form);
>        try
>        {
>            for(param in postData)
>            {
>                  var   input = document.createElement('input');
>                      input.setAttribute('name', param);
>                      input.setAttribute('value', postData[param]);
>                      $(input).appendTo(form);
>            }
>        }
>        catch(e) {}
>        //set attributes
>        $(form).css('position', 'absolute');
>        $(form).css('top', '-1200px');
>        $(form).css('left', '-1200px');
>        $(form).appendTo('body');
>        return form;
>    },
>    ajaxFileUpload: function(s) {
>        // TODO introduce global settings, allowing the client to modify
> them for all requests, not only timeout
>        s = jQuery.extend({}, jQuery.ajaxSettings, s);
>        var id = new Date().getTime()
>        var form = jQuery.createUploadForm(id, s.fileElementId, s.data);
>        var io = jQuery.createUploadIframe(id, s.secureuri);
>        var frameId = 'jUploadFrame' + id;
>        var formId = 'jUploadForm' + id;
>        // Watch for a new set of requests
>        if ( s.global && ! jQuery.active++ )
>        {
>            jQuery.event.trigger( "ajaxStart" );
>        }
>        var requestDone = false;
>        // Create the request object
>        var xml = {}
>        if ( s.global )
>            jQuery.event.trigger("ajaxSend", [xml, s]);
>        // Wait for a response to come back
>        var uploadCallback = function(isTimeout)
>        {
>            var io = document.getElementById(frameId);
>            try
>            {
>                if(io.contentWindow)
>                {
>                     xml.responseText =
>
io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null
> ;
>                     xml.responseXML =
>
io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:
> io.contentWindow.document;
>
>                }else if(io.contentDocument)
>                {
>                     xml.responseText =
>
io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:
> null;
>                    xml.responseXML =
>
io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocum
> ent:io.contentDocument.document;
>                }
>            }catch(e)
>            {
>                jQuery.handleError(s, xml, null, e);
>            }
>            if ( xml || isTimeout == "timeout")
>            {
>                requestDone = true;
>                var status;
>                try {
>                    status = isTimeout != "timeout" ? "success" : "error";
>                    // Make sure that the request was successful or
> notmodified
>                    if ( status != "error" )
>                    {
>                        // process the data (runs the xml through httpData
> regardless of callback)
>                        var data = jQuery.uploadHttpData( xml, s.dataType
);
>
>                        // If a local callback was specified, fire it and
> pass it the data
>                        if ( s.success )
>                            s.success( data, status );
>
>                        // Fire the global callback
>                        if( s.global )
>                            jQuery.event.trigger( "ajaxSuccess", [xml, s]
);
>                    } else
>                        jQuery.handleError(s, xml, status);
>                } catch(e)
>                {
>                    status = "error";
>                    jQuery.handleError(s, xml, status, e);
>                }
>
>                // The request was completed
>                if( s.global )
>                    jQuery.event.trigger( "ajaxComplete", [xml, s] );
>
>                // Handle the global AJAX counter
>                if ( s.global && ! --jQuery.active )
>                    jQuery.event.trigger( "ajaxStop" );
>
>                // Process result
>                if ( s.complete )
>                    s.complete(xml, status);
>
>                jQuery(io).unbind()
>
>                setTimeout(function()
>                                    {    try
>                                        {
>                                            $(io).remove();
>                                            $(form).remove();
>
>                                        } catch(e)
>                                        {
>                                            jQuery.handleError(s, xml,
null,
> e);
>                                        }
>
>
>                                    }, 100)
>
>                xml = null
>
>            }
>        }
>        // Timeout checker
>        if ( s.timeout > 0 )
>        {
>            setTimeout(function(){
>                // Check to see if the request is still happening
>                if( !requestDone ) uploadCallback( "timeout" );
>            }, s.timeout);
>        }
>        try
>        {
>           // var io = $('#' + frameId);
>            var form = $('#' + formId);
>            $(form).attr('action', s.url);
>            $(form).attr('method', 'POST');
>            $(form).attr('target', frameId);
>            if(form.encoding)
>            {
>                form.encoding = 'multipart/form-data';
>            }
>            else
>            {
>                form.enctype = 'multipart/form-data';
>            }
>            $(form).submit();
>
>        } catch(e)
>        {
>            jQuery.handleError(s, xml, null, e);
>        }
>        if(window.attachEvent){
>            document.getElementById(frameId).attachEvent('onload',
> uploadCallback);
>        }
>        else{
>            document.getElementById(frameId).addEventListener('load',
> uploadCallback, false);
>        }
>        return {abort: function () {}};
>
>    },
>
>    uploadHttpData: function( r, type ) {
>        var data = !type;
>        data = type == "xml" || data ? r.responseXML : r.responseText;
>        // If the type is "script", eval it in global context
>        if ( type == "script" )
>            jQuery.globalEval( data );
>        // Get the JavaScript object, if JSON is used.
>        if ( type == "json" )
>            eval( "data = " + data );
>        // evaluate scripts within html
>        if ( type == "html" )
>            jQuery("<div>").html(data).evalScripts();
>            //alert($('param',
> data).each(function(){alert($(this).attr('value'));}));
>        return data;
>    }
> })
>
> But during my tesing, the code appears to run ok only in IE (IE 7). It
> failed on Firefox (3.0.10), Safari (3.2.1) and Chrome (1.0.154.65), with
> simply no request received from the server after “jQuery(form).submit();”
> and no exception thrown or captured either. I reported the problem back
but
> so far no reply (I am not a Javascript expert).
>
> Hope your ajax file upload approach will also handle UTF8 encoded caption
–
> I certainly would do some testing when your code is ready
> The other issue in my mind about file upload is if “multi-file upload in
one
> submit” could be achieved. I saw it in Flash version where user selects
> multiple files using Window’s file selection while keeping control key
down.
> I suppose this ability would bring Struts’ file upload to the next level.
>
> Kind regards,
>
> Qunhuan
>
> -----Original Message-----
> From: Wes Wannemacher [mailto:wesw@wantii.com]
> Sent: 03 June 2009 22:03
> To: Struts Users Mailing List
> Subject: Re: About the "struts.multipart.saveDir" for file upload
>
>
> I'll check it out, I just wanted to improve what we had because it's
> currently impossible to do things like an AJAX upload with accurate
> progress bar. After I get the plugin (1.0-SNAPSHOT, which is the maven
> way of saying beta) committed to the sandbox, I'll whip up a quick
> example of how to do an AJAX w/progress bar using struts.
>
> -Wes
>
> On Wed, Jun 3, 2009 at 5:00 PM, Andy <an...@hotmail.com> wrote:
>>
>> That's great Wes.  I am using the file upload but only sparingly (and
> hacked) due to some existing glitches.
>>
>>
>>
>> I read how the Stripes framework does file upload:
>  http://www.stripesframework.org/display/stripes/File+Uploads
>>
>>
>>
>> Thought you might find it interesting/useful..
>>
>>
>>
>> Andy
>>
>>
>>
>>> Date: Wed, 3 Jun 2009 16:48:56 -0400
>>> Subject: Re: About the "struts.multipart.saveDir" for file upload
>>> From: wesw@wantii.com
>>> To: user@struts.apache.org
>>>
>>> I don't know if I would suggest it, but you might be able to call -
>>>
>>> Dispatcher.getInstance().setMultipartSaveDir(String path)
>>>
>>> Now, I can't remember if there is one dispatcher per thread, so you
>>> might have to call it in an interceptor.
>>>
>>> However, I would strongly suggest against doing that.
>>>
>>> I am working on an enhanced file upload plugin right now and will
>>> probably commit it to the sandbox by tomorrow. The problem with the
>>> stock file upload capability is that the FileItemFactory and
>>> FileUpload objects are not available to be overridden, and hardly any
>>> configuration is made visible. So, I've got a new
>>> JakartaMultiPartRequest class I'll have out by tomorrow.
>>>
>>> -Wes
>>>
>>> On Wed, Jun 3, 2009 at 4:37 PM, Andy <an...@hotmail.com> wrote:
>>> >
>>> > It defaults but I think he's wondering how he can set the dir
> programatically.
>>> >
>>> >
>>> >
>>> >> Date: Wed, 3 Jun 2009 15:35:33 -0500
>>> >> Subject: Re: About the "struts.multipart.saveDir" for file upload
>>> >> From: burtonrhodes@gmail.com
>>> >> To: user@struts.apache.org
>>> >>
>>> >> I wasn't aware that it was required. If you don't specify doesn't it
>>> >> default to the 'work' directory?
>>> >>
>>> >> On 6/3/09, Qunhuan Mei <qm...@qm18.wanadoo.co.uk> wrote:
>>> >> >
>>> >> > Hi,
>>> >> >
>>> >> > When implementing file upload, it is required to specify an
absolute
>>> >> > directory in struts.xml such as following:
>>> >> >
>>> >> > <constant name="struts.multipart.saveDir"
> value="C:/fileUploadTempDir"
>>> >> > />
>>> >> >
>>> >> > But this might be difficult to achieve, say when the project war is
> deployed
>>> >> > in a external shared server and we do not have much idea about the
> directory
>>> >> > structure of the target server machine.
>>> >> >
>>> >> > I was wondering if there is any recommended way to handle this
> issue.
>>> >> >
>>> >> > Ideally I would like to specify the directory in java code where I
> can
>>> >> > detect the current working directory and specify the saveDir
> accordingly. Is
>>> >> > this possible?
>>> >> >
>>> >> > Many thanks in advance,
>>> >> >
>>> >> > Qunhuan
>>> >> >
>>> >> >
>>> >> >
>>> >> >
>>> >> >
> ---------------------------------------------------------------------
>>> >> > To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
>>> >> > For additional commands, e-mail: user-help@struts.apache.org
>>> >> >
>>> >> >
>>> >>
>>> >> --
>>> >> Sent from my mobile device
>>> >>
>>> >> ---------------------------------------------------------------------
>>> >> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
>>> >> For additional commands, e-mail: user-help@struts.apache.org
>>> >>
>>> >
>>> > _________________________________________________________________
>>> > Windows Live™: Keep your life in sync.
>>> >
> http://windowslive.com/explore?ocid=TXT_TAGLM_WL_BR_life_in_synch_062009
>>>
>>>
>>>
>>> --
>>> Wes Wannemacher
>>> Author - Struts 2 In Practice
>>> Includes coverage of Struts 2.1, Spring, JPA, JQuery, Sitemesh and more
>>> http://www.manning.com/wannemacher
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
>>> For additional commands, e-mail: user-help@struts.apache.org
>>>
>>
>> _________________________________________________________________
>> Insert movie times and more without leaving Hotmail®.
>>
>
http://windowslive.com/Tutorial/Hotmail/QuickAdd?ocid=TXT_TAGLM_WL_HM_Tutori
> al_QuickAdd_062009
>
>
>
> --
> Wes Wannemacher
> Author - Struts 2 In Practice
> Includes coverage of Struts 2.1, Spring, JPA, JQuery, Sitemesh and more
> http://www.manning.com/wannemacher
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>



-- 
Wes Wannemacher
Author - Struts 2 In Practice
Includes coverage of Struts 2.1, Spring, JPA, JQuery, Sitemesh and more
http://www.manning.com/wannemacher

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org





---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Ajax file upload + RE: About the "struts.multipart.saveDir" for file upload

Posted by Wes Wannemacher <we...@wantii.com>.
Really, I haven't gotten that far yet, I am only working to improve
the integration with Jakarta FileUpload. JFU is quite capable and
mature, but I figured the first step would be to expose more
functionality since there were a few JIRAs related to people asking
for more than what is currently offered.

I committed a partially complete plugin to the sandbox yesterday
before I left my office, but I still need to glue it together with
configuration, etc. (and work out a bug I realized I had in the middle
of the night last night). Once I get the plugin to an installable
state, you can check it out. I figure the first step is to make the
plugin work, then the next step is building an example UI. I am not
sure how I am going to build the example UI, but JQuery is probably
the most likely candidate for me.

As far as selecting multiple files with Ctrl-Click, I'm not sure if
that is possible... Not from a struts/jquery perspective, but I don't
know if the browser will let you do that. I think Flash may be the
only option (or a java applet or something, but flash is more likely),
so we can come back to that later.

-Wes

On Thu, Jun 4, 2009 at 4:07 AM, Qunhuan Mei <qm...@qm18.wanadoo.co.uk> wrote:
> Hi Wes,
>
> Struts’ ajax file upload would be very interesting to me since I have
> implemented jQuery (http://www.phpletter.com/Our-Projects/AjaxFileUpload/)
> and Struts for ajax file upload in my application and had one or two
> problem(s).
>
> FYI: My use case is to upload a file, together with utf8 encoded caption.
> The problem I had is utf8 encoded caption needs to be sent via HTTP POST, it
> won’t work with HTTP get. But the jQuery arrangement is sending file in POST
> while sending caption in Get. So what I did is to send caption and file in
> two POSTs which cause other complications. Later the author (Øyvind Saltvik
> oyvind.saltvik@gmail.com) sent me the following code contributed by
> (Prokofiev Nikolay nprokofiev@gmail.com) which added the parameter POSTing
> (e.g. caption) to jQuery’s file upload.
>
> $.ajaxFileUpload
>        (
>            {
>                url:document.location+'&ajax=true',
>                secureuri:false,
>                fileElementId:'fileToUpload',
>                data: {foo: 'ghffgh', bar: 'fghfhgg'},
>                dataType: 'json',
>                success: function (data, status)
>                {
>                    if(typeof(data.error) != 'undefined')
>                    {
>                        if(data.error != '')
>                        {
>                            alert(data.error);
>                        }else
>                        {
>                            alert(data.msg);
>                        }
>                    }
>                },
>                error: function (data, status, e)
>                {
>                    alert(e);
>                }
>            }
>        )
>
> here is the script:
> jQuery.extend({
>    createUploadIframe: function(id, uri)
>    {
>            //create frame
>            var frameId = 'jUploadFrame' + id;
>
>            if(window.ActiveXObject) {
>                var io = document.createElement('<iframe id="' + frameId +
> '" name="' + frameId + '" />');
>                if(typeof uri== 'boolean'){
>                    io.src = 'javascript:false';
>                }
>                else if(typeof uri== 'string'){
>                    io.src = uri;
>                }
>            }
>            else {
>                var io = document.createElement('iframe');
>                io.id = frameId;
>                io.name = frameId;
>            }
>            io.style.position = 'absolute';
>            io.style.top = '-1000px';
>            io.style.left = '-1000px';
>
>            document.body.appendChild(io);
>
>            return io
>    },
>    createUploadForm: function(id, fileElementId, postData)
>    {
>        //create form
>        var formId = 'jUploadForm' + id;
>        var fileId = 'jUploadFile' + id;
>        var form = $('<form  action="" method="POST" name="' + formId + '"
> id="' + formId + '" enctype="multipart/form-data"></form>');
>        var oldElement = $('#' + fileElementId);
>        var newElement = $(oldElement).clone();
>        $(oldElement).attr('id', fileId);
>        $(oldElement).before(newElement);
>        $(oldElement).appendTo(form);
>        try
>        {
>            for(param in postData)
>            {
>                  var   input = document.createElement('input');
>                      input.setAttribute('name', param);
>                      input.setAttribute('value', postData[param]);
>                      $(input).appendTo(form);
>            }
>        }
>        catch(e) {}
>        //set attributes
>        $(form).css('position', 'absolute');
>        $(form).css('top', '-1200px');
>        $(form).css('left', '-1200px');
>        $(form).appendTo('body');
>        return form;
>    },
>    ajaxFileUpload: function(s) {
>        // TODO introduce global settings, allowing the client to modify
> them for all requests, not only timeout
>        s = jQuery.extend({}, jQuery.ajaxSettings, s);
>        var id = new Date().getTime()
>        var form = jQuery.createUploadForm(id, s.fileElementId, s.data);
>        var io = jQuery.createUploadIframe(id, s.secureuri);
>        var frameId = 'jUploadFrame' + id;
>        var formId = 'jUploadForm' + id;
>        // Watch for a new set of requests
>        if ( s.global && ! jQuery.active++ )
>        {
>            jQuery.event.trigger( "ajaxStart" );
>        }
>        var requestDone = false;
>        // Create the request object
>        var xml = {}
>        if ( s.global )
>            jQuery.event.trigger("ajaxSend", [xml, s]);
>        // Wait for a response to come back
>        var uploadCallback = function(isTimeout)
>        {
>            var io = document.getElementById(frameId);
>            try
>            {
>                if(io.contentWindow)
>                {
>                     xml.responseText =
> io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null
> ;
>                     xml.responseXML =
> io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:
> io.contentWindow.document;
>
>                }else if(io.contentDocument)
>                {
>                     xml.responseText =
> io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:
> null;
>                    xml.responseXML =
> io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocum
> ent:io.contentDocument.document;
>                }
>            }catch(e)
>            {
>                jQuery.handleError(s, xml, null, e);
>            }
>            if ( xml || isTimeout == "timeout")
>            {
>                requestDone = true;
>                var status;
>                try {
>                    status = isTimeout != "timeout" ? "success" : "error";
>                    // Make sure that the request was successful or
> notmodified
>                    if ( status != "error" )
>                    {
>                        // process the data (runs the xml through httpData
> regardless of callback)
>                        var data = jQuery.uploadHttpData( xml, s.dataType );
>
>                        // If a local callback was specified, fire it and
> pass it the data
>                        if ( s.success )
>                            s.success( data, status );
>
>                        // Fire the global callback
>                        if( s.global )
>                            jQuery.event.trigger( "ajaxSuccess", [xml, s] );
>                    } else
>                        jQuery.handleError(s, xml, status);
>                } catch(e)
>                {
>                    status = "error";
>                    jQuery.handleError(s, xml, status, e);
>                }
>
>                // The request was completed
>                if( s.global )
>                    jQuery.event.trigger( "ajaxComplete", [xml, s] );
>
>                // Handle the global AJAX counter
>                if ( s.global && ! --jQuery.active )
>                    jQuery.event.trigger( "ajaxStop" );
>
>                // Process result
>                if ( s.complete )
>                    s.complete(xml, status);
>
>                jQuery(io).unbind()
>
>                setTimeout(function()
>                                    {    try
>                                        {
>                                            $(io).remove();
>                                            $(form).remove();
>
>                                        } catch(e)
>                                        {
>                                            jQuery.handleError(s, xml, null,
> e);
>                                        }
>
>
>                                    }, 100)
>
>                xml = null
>
>            }
>        }
>        // Timeout checker
>        if ( s.timeout > 0 )
>        {
>            setTimeout(function(){
>                // Check to see if the request is still happening
>                if( !requestDone ) uploadCallback( "timeout" );
>            }, s.timeout);
>        }
>        try
>        {
>           // var io = $('#' + frameId);
>            var form = $('#' + formId);
>            $(form).attr('action', s.url);
>            $(form).attr('method', 'POST');
>            $(form).attr('target', frameId);
>            if(form.encoding)
>            {
>                form.encoding = 'multipart/form-data';
>            }
>            else
>            {
>                form.enctype = 'multipart/form-data';
>            }
>            $(form).submit();
>
>        } catch(e)
>        {
>            jQuery.handleError(s, xml, null, e);
>        }
>        if(window.attachEvent){
>            document.getElementById(frameId).attachEvent('onload',
> uploadCallback);
>        }
>        else{
>            document.getElementById(frameId).addEventListener('load',
> uploadCallback, false);
>        }
>        return {abort: function () {}};
>
>    },
>
>    uploadHttpData: function( r, type ) {
>        var data = !type;
>        data = type == "xml" || data ? r.responseXML : r.responseText;
>        // If the type is "script", eval it in global context
>        if ( type == "script" )
>            jQuery.globalEval( data );
>        // Get the JavaScript object, if JSON is used.
>        if ( type == "json" )
>            eval( "data = " + data );
>        // evaluate scripts within html
>        if ( type == "html" )
>            jQuery("<div>").html(data).evalScripts();
>            //alert($('param',
> data).each(function(){alert($(this).attr('value'));}));
>        return data;
>    }
> })
>
> But during my tesing, the code appears to run ok only in IE (IE 7). It
> failed on Firefox (3.0.10), Safari (3.2.1) and Chrome (1.0.154.65), with
> simply no request received from the server after “jQuery(form).submit();”
> and no exception thrown or captured either. I reported the problem back but
> so far no reply (I am not a Javascript expert).
>
> Hope your ajax file upload approach will also handle UTF8 encoded caption –
> I certainly would do some testing when your code is ready
> The other issue in my mind about file upload is if “multi-file upload in one
> submit” could be achieved. I saw it in Flash version where user selects
> multiple files using Window’s file selection while keeping control key down.
> I suppose this ability would bring Struts’ file upload to the next level.
>
> Kind regards,
>
> Qunhuan
>
> -----Original Message-----
> From: Wes Wannemacher [mailto:wesw@wantii.com]
> Sent: 03 June 2009 22:03
> To: Struts Users Mailing List
> Subject: Re: About the "struts.multipart.saveDir" for file upload
>
>
> I'll check it out, I just wanted to improve what we had because it's
> currently impossible to do things like an AJAX upload with accurate
> progress bar. After I get the plugin (1.0-SNAPSHOT, which is the maven
> way of saying beta) committed to the sandbox, I'll whip up a quick
> example of how to do an AJAX w/progress bar using struts.
>
> -Wes
>
> On Wed, Jun 3, 2009 at 5:00 PM, Andy <an...@hotmail.com> wrote:
>>
>> That's great Wes.  I am using the file upload but only sparingly (and
> hacked) due to some existing glitches.
>>
>>
>>
>> I read how the Stripes framework does file upload:
>  http://www.stripesframework.org/display/stripes/File+Uploads
>>
>>
>>
>> Thought you might find it interesting/useful..
>>
>>
>>
>> Andy
>>
>>
>>
>>> Date: Wed, 3 Jun 2009 16:48:56 -0400
>>> Subject: Re: About the "struts.multipart.saveDir" for file upload
>>> From: wesw@wantii.com
>>> To: user@struts.apache.org
>>>
>>> I don't know if I would suggest it, but you might be able to call -
>>>
>>> Dispatcher.getInstance().setMultipartSaveDir(String path)
>>>
>>> Now, I can't remember if there is one dispatcher per thread, so you
>>> might have to call it in an interceptor.
>>>
>>> However, I would strongly suggest against doing that.
>>>
>>> I am working on an enhanced file upload plugin right now and will
>>> probably commit it to the sandbox by tomorrow. The problem with the
>>> stock file upload capability is that the FileItemFactory and
>>> FileUpload objects are not available to be overridden, and hardly any
>>> configuration is made visible. So, I've got a new
>>> JakartaMultiPartRequest class I'll have out by tomorrow.
>>>
>>> -Wes
>>>
>>> On Wed, Jun 3, 2009 at 4:37 PM, Andy <an...@hotmail.com> wrote:
>>> >
>>> > It defaults but I think he's wondering how he can set the dir
> programatically.
>>> >
>>> >
>>> >
>>> >> Date: Wed, 3 Jun 2009 15:35:33 -0500
>>> >> Subject: Re: About the "struts.multipart.saveDir" for file upload
>>> >> From: burtonrhodes@gmail.com
>>> >> To: user@struts.apache.org
>>> >>
>>> >> I wasn't aware that it was required. If you don't specify doesn't it
>>> >> default to the 'work' directory?
>>> >>
>>> >> On 6/3/09, Qunhuan Mei <qm...@qm18.wanadoo.co.uk> wrote:
>>> >> >
>>> >> > Hi,
>>> >> >
>>> >> > When implementing file upload, it is required to specify an absolute
>>> >> > directory in struts.xml such as following:
>>> >> >
>>> >> > <constant name="struts.multipart.saveDir"
> value="C:/fileUploadTempDir"
>>> >> > />
>>> >> >
>>> >> > But this might be difficult to achieve, say when the project war is
> deployed
>>> >> > in a external shared server and we do not have much idea about the
> directory
>>> >> > structure of the target server machine.
>>> >> >
>>> >> > I was wondering if there is any recommended way to handle this
> issue.
>>> >> >
>>> >> > Ideally I would like to specify the directory in java code where I
> can
>>> >> > detect the current working directory and specify the saveDir
> accordingly. Is
>>> >> > this possible?
>>> >> >
>>> >> > Many thanks in advance,
>>> >> >
>>> >> > Qunhuan
>>> >> >
>>> >> >
>>> >> >
>>> >> >
>>> >> >
> ---------------------------------------------------------------------
>>> >> > To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
>>> >> > For additional commands, e-mail: user-help@struts.apache.org
>>> >> >
>>> >> >
>>> >>
>>> >> --
>>> >> Sent from my mobile device
>>> >>
>>> >> ---------------------------------------------------------------------
>>> >> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
>>> >> For additional commands, e-mail: user-help@struts.apache.org
>>> >>
>>> >
>>> > _________________________________________________________________
>>> > Windows Live™: Keep your life in sync.
>>> >
> http://windowslive.com/explore?ocid=TXT_TAGLM_WL_BR_life_in_synch_062009
>>>
>>>
>>>
>>> --
>>> Wes Wannemacher
>>> Author - Struts 2 In Practice
>>> Includes coverage of Struts 2.1, Spring, JPA, JQuery, Sitemesh and more
>>> http://www.manning.com/wannemacher
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
>>> For additional commands, e-mail: user-help@struts.apache.org
>>>
>>
>> _________________________________________________________________
>> Insert movie times and more without leaving Hotmail®.
>>
> http://windowslive.com/Tutorial/Hotmail/QuickAdd?ocid=TXT_TAGLM_WL_HM_Tutori
> al_QuickAdd_062009
>
>
>
> --
> Wes Wannemacher
> Author - Struts 2 In Practice
> Includes coverage of Struts 2.1, Spring, JPA, JQuery, Sitemesh and more
> http://www.manning.com/wannemacher
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>



-- 
Wes Wannemacher
Author - Struts 2 In Practice
Includes coverage of Struts 2.1, Spring, JPA, JQuery, Sitemesh and more
http://www.manning.com/wannemacher

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org