通过后期处理上传进度

时间:2014-12-29 14:00:35

标签: php jquery css html5

我有一个上传表单,用户可以上传文件。上传完成后,文件将进行后期处理,有时上传完成后处理时间最长为10-15秒。

上传完成后,进度条为100%,但是如何检测文件何时完成,这样您就可以在文件处理过程中向用户显示“请稍候”的标志..用户可能会认为浏览器已冻结og崩溃,因为进度条为100%但没有任何事情发生..

纯HTML5 + javascript中的客户端解决方案是首选,但不是必须的:)

6 个答案:

答案 0 :(得分:8)

尝试

HTML

<progress min="0" max="10000"></progress>
<output for="progress"></output>
<output for="progress"></output>
<br />
<table id="results"></table>

JS

var len = arr.length // file length
    , start = 0 // update progress
    , outputs = $("output[for=progress]") // notifications
    , progress = $("progress")
    , results = $("#results") // post processing 
    // gif spinner
    , spinner = $("<img />", {
    "src": "data:image/gif;charset=binary;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQACgABACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkEAAoAAgAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkEAAoAAwAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkEAAoABAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQACgAFACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQACgAGACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAAKAAcALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA=="
});
// upload file
var request = function () {
    progress.prop("max", len);
    s = setInterval(function () {
        progress.prop("value", ++start);
        outputs.eq(0)
            .text("uploading file...")
    }, 1)
    return $.post("/echo/json/", {
        json: JSON.stringify(arr)
    })
    .then(function (data) {
        clearInterval(s)
        s = null;
        progress.prop("value", len);
        outputs.eq(0)
            .html("upload complete ! <br />processing response, please wait...")
        .next(outputs.eq(1))
        .html(spinner);
        return data
    })
};

request()
.then(function (data) {
    // do post upload processing stuff
    var process = function() {
    var dfd = new $.Deferred();
    // processing...
    t = setTimeout(function () {
        data.forEach(function (res) {
            results.append(
            $("<tr />", {
                "html": $("<td />", {
                    "html": res.value
                })
            }))
        });
        if (results.find("tr").length === len) {
           dfd.resolve("complete !")
        }
    }, 1 + Math.floor(Math.random() * 15000));
        return dfd.promise()
    };
    // do stuff when all post processing complete
    process().then(function(complete) {
       outputs.eq(0).empty()
       .next(outputs.eq(1))
       .html(complete);
       clearTimeout(t);
       t = null;
    })
});

jsfiddle http://jsfiddle.net/guest271314/d2szrs20/

答案 1 :(得分:5)

由于您有显示表单流程的进度条要在处理过程中添加更多详细信息,您可以添加如下图像

它会向用户显示您的表单仍在处理create your custom image here

enter image description here

这可能有助于用户 - 浏览器尚未冻结。

答案 2 :(得分:2)

我正在使用自定义上传小部件。在服务器端,我在请求更新时向客户端发送以下信息:收到的文件的百分比加上状态消息。通过该消息,我可以提供额外的反馈,例如后期处理的哪个步骤正在发生或显示错误。

答案 3 :(得分:2)

我正在使用名为pekeupload的jquery插件 它体积小,易于实现和定制

http://plugins.jquery.com/pekeUpload/ https://github.com/pekebyte/pekeUpload

我希望这能帮到你

最好的

答案 4 :(得分:2)

的Javascript

function initialize_progress(element)
{
    //initializations!
    $(element).hide();
    $(element).find('.progress-bar').prop('style','width: 0');
}


function getProgress(process_id){
    var re=new RegExp(process_id+"=[^;]+", "i") //construct RE to search for target name/value pair
    if (document.cookie.match(re)) //if cookie found
        return document.cookie.match(re)[0].split("=")[1] //return its value
    return null
}


function updateProgress(process_id, element){

    var percentage, message, name, failed;


    $(element).show();
    var myIntervalID = setInterval(function()
    {
        percentage = getProgress(process_id+"_percentage");
        name = getProgress(process_id+"_process_name");
        message = getProgress(process_id+"_message");
        failed = getProgress(process_id+"_process_failed");

        if(percentage) $(element).find('.progress-bar').css('width',percentage+'%').html(percentage+"% "+message);

    },2000);
}

//initialize progress  bar
//initialize_progress(".progress");

$(".upload-button").click(function()
{


    //set listener
    updateProgress('upload_the_pix', ".progress")


    var request = $.get( "http://example.com/?progress", function(data) {
        alert(data);
    })
        .done(function() {
            alert( "second success" )
        }).fail(function() {
            alert( "error" );
        }).always(function() {
            alert( "finished" );
        });


});

HTML

 <div class="progress">
                        <div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width: 0%">

                        </div>
                    </div>

服务器端进程 - 使用PHP

class ProcessProgress
{
    protected static $process_id; //current process_id
    protected static $process_name; //current process name
    protected static $debug_mode = false;
    protected static $process_killed = false;


    /**
     * Make settings for process setup
     * @param $settings
     * Example:
     * $settings=array(
     *   'process_id'    => 'upload_photos' //must be provided
         'process_name'  =>'Database Wipe', //tile of this process
       );
     */
    public static function settings($settings)
    {
        # process id must be set

        #make array keys properties
        if( is_array($settings) ){
            foreach($settings as $key => $value){
                self::$$key = $value;
            }
        }

        if(self::$debug_mode && !self::$process_id) exit('process_id must me provided in settings array');

        if(isset($_COOKIE[self::$process_id."_percentage"])){
            unset($_COOKIE[self::$process_id."_percentage"]);
            unset($_COOKIE[self::$process_id."_message"]);
            unset($_COOKIE[self::$process_id."_process_name"]);
            unset($_COOKIE[self::$process_id."_process_complete"]);
            unset($_COOKIE[self::$process_id."_process_failed"]);
            unset($_COOKIE[self::$process_id."_process_killed"]);
        }
    }


    /**
     * Kill this process
     */
    public static function kill()
    {
        self::$process_killed = true;
    }


    /**
     * @param $percentage
     * @param $message
     * @param bool $complete
     * @param bool $failed
     * @return bool
     */
    public function setProgress($percentage, $message, $complete=false, $failed=false){

        $process_data = array(
            'percentage'=>$percentage,
            'message' => $message,
            'process_id' => self::$process_id,
            'process_name' => self::$process_name,
            'process_complete' => $complete,
            'process_failed' => $failed,
            'process_killed' => self::$process_killed,
        );


        setcookie(self::$process_id."_percentage", $percentage, time() + (86400 * 30)); // 86400 = 1 day
        setcookie(self::$process_id."_message", $message, time() + (86400 * 30)); // 86400 = 1 day
        setcookie(self::$process_id."_process_name", self::$process_name, time() + (86400 * 30)); // 86400 = 1 day
        setcookie(self::$process_id."_process_complete", $complete, time() + (86400 * 30)); // 86400 = 1 day
        setcookie(self::$process_id."_process_failed", $failed, time() + (86400 * 30)); // 86400 = 1 day
        setcookie(self::$process_id."_process_killed", self::$process_killed, time() + (86400 * 30)); // 86400 = 1 day


        //verify
        if(isset($_COOKIE[self::$process_id])) return true;

        #delay 1 second
        //sleep(1);
    }
}

单击按钮时服务器端的用法 http://example.com/?progress

 if(isset($_GET['progress'])){
ProcessProgress::settings(array(
    'process_id' => 'upload_the_pix',
    'process_name' => 'Picture Upload',
));

ProcessProgress::setProgress(0, 'Initializing');

for($count=0; $count < 10001; $count++){

    switch($count){
        case 1000:
            ProcessProgress::setProgress(10, 'Coping files');
            break;

        case 2000:
            ProcessProgress::setProgress(20, 'Setting up email');
            break;

        case 3000:
            ProcessProgress::setProgress(30, 'Looking up things');
            break;

        case 4000:
            ProcessProgress::setProgress(40, 'Milking your cow');
            break;

        case 5000:
            ProcessProgress::setProgress(50, 'Syncing contacts');
            break;


        case 6000:
            ProcessProgress::setProgress(60, 'Updating Facebook profile');
            break;

        case 7000:
            ProcessProgress::setProgress(70, 'Calling your girl friend');
            break;


        case 8000:
            ProcessProgress::setProgress(80, 'Making things up');
            break;

        case 9000:
            ProcessProgress::setProgress(90, 'Feeding your dogs');
            break;

        case 10000:
            ProcessProgress::setProgress(100, 'Done. Congrats');
            break;
    }
}

}

答案 5 :(得分:0)

无论服务器/客户端技术如何,您都可以向两个方向发展:

1。首先是线性处理(这是你当前的方式)

将服务器上的文件从temp send echo移动到用户之后&#34;文件已成功上传。处理......&#34;或者只是在JS中你可以在没有来自服务器的任何信息的情况下在上传完成事件上显示消息或者进行另一个ajax调用来检查...,实际上,有很多方法可以做到这一点..点是在上传服务器继续文件处理之后(例如OCR 30页刚刚上传的PDF或其他)用户必须等待服务器完成处理。 这很有气味,因为如果很少有用户同时上传文件,所有内容将同时处理,您的服务器将快速达到100%......所以这就把我带到了

2。使用作业/消息队列

上传文档后,将文件作业放入队列,并在处理完成时(例如将文档上传到issuu时)通知用户您将向他发送邮件(或用于通知用户的任何方式)。这样处理上传文件(可能在另一台机器上;))一个接一个地完成,用户不必等待文件处理完成......这是首选方式。

对于作业/消息队列,您可以使用:

两者都适用于Java,.NET,Ruby,Python,PHP,Perl,C / C ++,Erlang,Node.js,什么不是......

祝你好运:)