#1285 ✓not_for_core
GD

File upload Management

Reported by GD | November 21st, 2011 @ 03:50 PM

Hi,

I would like to suggest the possibility to manage file uploads with Ajax request.

I created a class which sends one or multiple files via an Ajax request (with queue management). Everything works perfectly (no Flash, just pure html/js with prototype).

But there is one major problem, the only way to get the upload progress (to make a progress bar obviously) is with the 'xhr.upload.onprogress' method which is not implemented in Prototype (If it is possible with 'onInteractive', please, tell me how, I wasnt able to get it to work).

As a matter of fact, since the request is created and sent within the Ajax.Request class constructor, it's impossible to modify the 'transport' object after creation but before sending the request.

Easily enough, only 2 lines of code are necessary in Prototype to make it work, right in the middle of that very constructor (line 1492 [Ajax.Request.initialize()]) :

  initialize: function($super, url, options) {
    $super(options);
    this.transport = Ajax.getTransport();
    this.request(url);
  },

becomming :

  initialize: function($super, url, options) {
    $super(options);
    this.transport = Ajax.getTransport();

    // NEW LINES
    if (options && options.onUpload && Object.isFunction(options.onUpload))
        this.transport.upload.onprogress = options.onUpload;

    this.request(url);
  },

Allowing me to do :

new Ajax.Request ('/path/to/script', {
    method: 'post',
    requestHeaders: {
        'Content-Type': "application/octet-stream",
    },
    postBody: $('input_file_id,'),
    onUpload: function (data) {
        if (data.lengthComputable)
            // Displaying percent uploaded, draw a progress bar, etc...
            $('ProgressElement').update(Math.floor(100 * data.loaded / data.total));
    },
    onSuccess: function (xhr) {
        $('ProgressElement').update('OK');
    }
});

Or, as I'm sure you will, make something clever available within the onInteractive method.

PS : By the way, I don't know how I could possibly thank you enough for the time you made me save by using Prototype (and don't get me started with Explorer compatibility...) so, THANK YOU !

Comments and changes to this ticket

  • Victor

    Victor November 28th, 2011 @ 08:01 AM

    No changes are needed - you can just create new class and assign onprogress handler in overridden method, e.g.

    Ajax.UploadRequest = Class.create(Ajax.Request, {
      request: function($super, url) {
        if (Object.isFunction(this.options.onUpload))
          this.transport.upload.onprogress = this.options.onUpload;
        $super(url);
      }
    });
    

    P.S. Also you can add your progress indicator and post data to the options of this new class, and make default content type, so your code will look like

    new Ajax.UploadRequest('/path/to/script', 'input_file_id', {
      progress: 'ProgressElement',
      onUpload: function (data) {
        if (data.lengthComputable)
          // Displaying percent uploaded, draw a progress bar, etc...
          this.progress.update(Math.floor(100 * data.loaded / data.total));
      },
      onSuccess: function () {
        this.progress.update('Done');
      }
    });
    
  • GD

    GD December 5th, 2011 @ 05:01 PM

    Yes, That what I did in the end, actually, since I didn't want to modify every instance of Prototype for each site and after each update. I also wanted to leave it untouched so I now always carry my extended Upload Class.

    I just thought that you might be interrested in including this "Javascript only" Upload feature in the Prototype core as there is quite more fonctionnality/methods available from the xhr.upload than just 'onprogress' (like onabort, onerror, onload, onloadstart, onloadend).

  • Andrew Dupont

    Andrew Dupont December 5th, 2011 @ 11:53 PM

    • State changed from “new” to “not_for_core”
    • Importance changed from “” to “Low”

    Sounds awesome, but I don't think it's a common enough use case to warrant inclusion in core. Please do consider releasing it as an add-on, though.

  • kemas

    kemas June 29th, 2012 @ 04:42 AM

    Hi All...
    can u give me a sample or demo using that script for upload file.
    i'm newbie for ajax prototype.

    Thank's Before, For share This code at here

  • GD

    GD June 29th, 2012 @ 04:29 PM

    Hi,

    Unfortunately, I never had the time to write the whole thing with every methods implemented and commented, much less release a plug-in, but I can post here the code I wrote then.

    Just keep in mind that this was always intended to be used internally (web admin / back office) and not in a public production server. That being said, it's been used every day (and a lot) by several users for several months now without any pb so...
    Additionally, as xmlhttp2 goes, it is obviously not compatible with Internet Explorer... (here is the current browser support situation Link ).
    The script handles this and displays a good old upload button if the browser doesn't support xmlhttpRequest2.

    Usage :

    The file contains 3 classes

    • "Ajax.Uploader" (extends Ajax.Request) : adds upload to the Ajax.Request class,

    • "Uploader" : the Upload Object. Handles the drawing of the button (with unique ID), the files queue, the progress, etc...

    • "UploadManager" is the static wrapper class that handles all the upload buttons on the page (Uploader objects), sets the CSS (generic and button specific), holds the config (system, UI, HTML, CSS...), and have the method witch actually loads everything (init & autoload). A lot of that code will be useless to you as it was intended to allow css formatting when calling the add method (with the settings object, see below) when I thought I would have time to make it generic enough to publish it.

    First, because I'm using Symfony and for internationalization purposes, the html code for the button is generated server side (Ajax request). The same php script is used for returning the button code and handling the upload process (depending on whether the request is GET or POST).

    Three ways to create an upload button :

    • By instanciating the class yourself :
    var settings = {}
    new Uploader('element', '/path/to/your/php/script.php', settings)
    

    'Element' can either be a string (html id) or a prototype extended HTML element. It will be replaced by the uploader. Of course, this will fail if DOM isn't ready... or element doesn't exist...

    • By calling the add method :
    UploadManager.add('element', '/path/to/your/php/script.php', settings);
    // last argument is the settings like css, some system settings, see UploadManager.config for that...
    

    This one does the same thing but handles the DOM so that you don't have to. This checks if the DOM is ready, and if not, queues the request in a stack that will be parsed as soon as the dom is ready). => UploadManager.init is called as soon as dom:loaded is triggered.

    • by adding an html class to an element that will automatically be added (by the same UploadManager.init)
       <a class="_mx_upload_autoload" href="/path/to/your/php/script.php"></a>
    

    Every failure / problem is reported as a log or warn or error in the Firebug console with links to the elements, so check it out if something doesn't work !

    I'm running out of free time, so I'll post the php server side code another time if you're interested...

    Since I obviously didn't do any documentation on this, feel free to ask. I'm giving you the file as is, that's why I tried to explain how it works. I tried to clean it up a bit, but hey, I know what it's like to read someone else's code, so... Good Luck !

  • kemas

    kemas July 2nd, 2012 @ 06:12 AM

    Hi Guillaume Dub,
    Thanks for your response.

    Can you share a link to a demo or split files I downloaded the full script for the demo "if you have free time" so I can see how to use it.
    Sorry bother you, I'm still new to using ajax prototype.

    sorry bother you again

    Thank's

  • GD

    GD July 3rd, 2012 @ 10:29 AM

    As I said, there's no public use of this code, so no demo link, I'll have to write one, and upload it somewhere.

    But, honnestly, there nothing to know about prototype here, just include the file, put a

    <a class="_mx_upload_autoload" href="/path/to/your/php/script.php"></a>
    

    tag in your html somewhere and that's it.

    My PHP wouldn't be of much help, I use Symfony, template files, language files... but here's the short version :

    <?
        // If file sent
        if ($_SERVER['REQUEST_METHOD'] == 'POST')
        {
            // Reading input stream (file being uploaded)
            $buffer = @file_get_contents('php://input');
    
            // Retrieving Content-Type, size and extension from headers
            $headers = apache_request_headers();
            $fileSize = (int)$headers['Content-Length'];
            $fileName = isset($headers['MX-FileUpload-Name']) ? $headers['MX-FileUpload-Name'] : '';
    
            // Do whatever you want with the file...
            @file_put_contents($_SERVER['DOCUMENT_ROOT'].'/some/path/'.$fileName, $buffer);
        }
        // Upload Button request
        else
        {
            $uploadID = '_mx_upload_file_picker_'.md5(getTime('ms').'_'.rand(0, 1000));
            $res = array(
                'UploadID'      => $uploadID,
                'HTML'          => @file_get_contents($_SERVER['DOCUMENT_ROOT'].'/res/tpl/upload.html'),
                'fileTPL'       => @file_get_contents($_SERVER['DOCUMENT_ROOT'].$ifcurl.'/res/tpl/upload.file.html'),
                'cancelled'     => 'SymfonyCancelledMsgInYourLanguage',
            );
            echo toJSON($res);
        }
        
        function toJSON ($data) {
            $data = json_encode($data);
            header('Pragma: no-cache');
            header('Cache-Control: no-cache, must-revalidate');
            header('Content-type: application/json; charset=UTF-8');
            header('X-JSON: '.$data);
            return $data;
        }
    
    ?>
    

    But, to be honnest, I would recommend that you learn Prototype first, before trying to implement a Javascript uploader with progress, though...

  • Template onweb

    Template onweb July 20th, 2017 @ 12:58 PM

    Hi dude, i have also find out one good template website

    Download Free Template

  • Blaine753

    Blaine753 March 21st, 2018 @ 11:49 AM

    These guys did nod to King Kong, head on over to the Edit Profile page. POF Login You will certainly have to create your login the old made method.

  • Blanton951

    Blanton951 March 27th, 2018 @ 07:58 AM

    The most effective component is when you have enlisted on gizmos iCloud Sign In for a formally set-up device, most likely to Settings and also look down to iCloud.

  • gmailloginfix

    gmailloginfix May 16th, 2018 @ 01:02 AM

    Guys, I dont think it would work without creating an account first so gmail sign in

    instadp

  • american express

    american express November 6th, 2018 @ 07:52 AM

    Want to confirm your American Express card online using americanexpress.com/confirmcard? Here we show you how to confirm your card both Online on Phone!

  • Aslly

    Aslly November 9th, 2018 @ 09:57 AM

    we are going to share some of the most important information regarding Chase Bank Login.

  • Emily Ava

    Emily Ava November 19th, 2018 @ 11:27 AM

    If you are looking to get the complete information for the Healthfusion Login then you are at the right place, because here we will tell you complete information.

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile ยป

The Prototype JavaScript library.

Shared Ticket Bins

People watching this ticket

Attachments

Pages