Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site













SourceForge.net Logo

SkylarkUpload

 

Skylark upload with ajax progress bar

 

 

SkylarkUpload.h

 

#ifndef _SkylarkUpload_SkylarkUpload_h_

#define _SkylarkUpload_SkylarkUpload_h_

 

#include <Skylark/Skylark.h>

 

using namespace Upp;

 

class SkylarkUpload : public SkylarkApp

{

    private:

 

        // root path for saving files

        String rootPath;

    

    protected:

    

    public:

    

        // constructor

        SkylarkUpload(String const &rPath);

        

        // get root path

        String const &GetRootPath(void) { return rootPath; }

        

};

 

SkylarkUpload &Upload();

 

#endif

 

 

 

SkylarkUpload.cpp

 

#include "SkylarkUpload.h"

 

 

SkylarkUpload &Upload()

{

    return (SkylarkUpload &)SkylarkApp::TheApp();

}

 

SkylarkUpload::SkylarkUpload(String const &rPath)

{

    root = "server";

    rootPath = rPath;

    RealizeDirectory(rootPath);

 

#ifdef _DEBUG

    prefork = 0;

    use_caching = false;

#endif

 

}

 

CONSOLE_APP_MAIN

{

#ifdef _DEBUG

    StdLogSetup(LOG_FILE|LOG_COUT);

    Ini::skylark_log = true;

#endif

 

    SkylarkUpload upload(AppendFileName(GetHomeDirectory(), "UPLOAD/"));

    

    upload.Run();

 

}

 

 

 

Handlers.icpp

 

#include "SkylarkUpload.h"

 

int ProgressHandler(int reason, Http &http, int size)

{

    // get the upload unique identifier

    String id = http["uploadid"];

    String currentId = "." + id + ".currentSize";

    String totalId = "." + id + ".totalSize";

    

    // must be reentrant

    INTERLOCKED {

        switch(reason)

        {

            // got headers ?

            case PROGRESS_HEADER:

            {

                http

                    .SessionSet(currentId, 0)

                    .SessionSet(totalId, size)

                ;

                break;

            }

                

            // reading contents ?

            case PROGRESS_CONTENT:

            {

                int oldPercent = http[currentId];

                int total = http[totalId];

 

                // take care to NOT return 100% up to upload ended really

                int percent = min(99, (int)(100.0 * size / total));

 

                // avoid unnnedded session storing

                if(oldPercent != percent)

                    http.SessionSet(currentId, percent);

                break;

            }

                

            // finished reading contents ?

            case PROGRESS_END:

            {

                // signals end by resetting total size

                http.SessionSet(totalId, 0);

                break;

            }

            

            // default, used by query handler

            default: // PROGRESS_QUERY

            {

                // check if key is there --> upload started

                int total = http[totalId];

                if(!IsNull(total))

                {

                    if(total)

                        // if upload not ended, return the progress %

                        return http[currentId];

                    else

                    {

                        // upload ended, nullify session variables and return 100%

                        http

                            .SessionSet(currentId, Null)

                            .SessionSet(totalId, Null)

                        ;

                        return 100;

                    }

                }

                else

                    // upload still not started, return 0 progress

                    return 0;

            }

        }

    }

    return true;

}

 

SKYLARK(Home, "home")

{

    // we need a session variable for upload id

    if(http["@__skylark_session_cookie__"].IsNull())

        http.NewSessionId();

    

    // show rootpath in html page

    http("UploadFolder", Upload().GetRootPath());

 

    http.RenderResult("SkylarkUpload/SkylarkUpload");

}

 

SKYLARK(Default, "**")

{

    http.Redirect(Home);

}

 

SKYLARK_PROGRESS(PostUpload, "upload:POST", &ProgressHandler)

{

    String fileName = AppendFileName(Upload().GetRootPath(), (String)http["filename"]);

 

    Value const &contents = http["filestoupload[]"];

    Value const &filenames = http["filestoupload.filename[]"];

    if(contents.IsNull() || filenames.IsNull())

        return;

    for(int i = 0; i < contents.GetCount(); i++)

        SaveFile(AppendFileName(Upload().GetRootPath(), (String)filenames[i]), contents[i]);

}

 

SKYLARK(Progress,"progress")

{

    int p = ProgressHandler(PROGRESS_QUERY, http, 0);

    http.Content("text/plain", Format("%d", p));

    http.Response(200, "OK");

}

 

 

SkylarkUpload.witz

 

<html>

    <head>

        <title>File Upload Progress Bar</title>

        <link rel='stylesheet' type='text/css' href='static/SkylarkUpload/SkylarkUpload.css'>

 

        <!-- this script does all the upload magics -->

        <script type='text/javascript' src='static/SkylarkUpload/upload.js'></script>

    </head>

    <body>

        <div id='bodyContainer'>

        

            <div id='header'>

                Skylark file upload demo

            </div>

            <br>

            <br>

            This demo supports uploading multiple files at once

            <br>

            Files will be uploaded in '$UploadFolder' folder on server

            <br>

            <br>

            <!--

                POST URL -- javascript code will read it and build the 'action' of following form

                You MUST insert in 'value' field the upload url (here 'upload')

            -->

            <input type='hidden' id='uploadurl' value='upload'>

            

            <!--

                progress handler URL -- javascript will use it to make periodic calls on server

                querying upload progress and showing it in progress bar

                You MUST insert in 'value' field the progress url (here 'progress')

            -->

            <input type='hidden' id='progressurl' value='progress'>

    

            <!--

                POST form

                action is a dummy value, will be filled by javascript code

                which sets the POST

            -->

            <form action='xxxxxx' method='POST' id='myForm' enctype='multipart/form-data' target='hidden_iframe' onsubmit='startUpload(this);'>

            

                <!--

                    ending [] in filestoupload[] makes a ValueArray of multipart data

                    in Skylark arrays will be :

                        filestoupload[]                    a ValueArray with file contents

                        filestoupload.content_type[]    a ValueArray with file content types

                        filestoupload.filename[]        a ValueArray with filenames

                    The 'multiple' field allows select and upload more files at once

                -->

                <input type='file' name='filestoupload[]' multiple=''>

                <br><br>

                <input type='submit' value='Start Upload'>

                <br>

            </form>

            

            <!-- Progress bar -->

            <div id='progress_container'>

                <div id='progress'></div>

            </div>

            

            <!--

                hidden frame doing the upload process

                it's used to 'free' the browser window during upload phase

            -->

            <iframe id='hidden_iframe' name='hidden_iframe' src='about:blank'></iframe>

    

            <!--

                these fields are used to build an unique identifier of this upload job

                in order to allow progress handler to identify correctly its related upload job

                (we need it because we can have more upload jobs calls on server

            -->

            <input type='hidden' id='session' value='$@__skylark_session_cookie__'>

            <input type='hidden' id='submittime' value=''>

        </div>

    </body>

</html>

 

 

 

 

Do you want to contribute?