Javascript jQuery和perl:基于“状态”的进度条;管道文件";,动态ajax

Javascript jQuery和perl:基于“状态”的进度条;管道文件";,动态ajax,javascript,jquery,ajax,perl,progress-bar,Javascript,Jquery,Ajax,Perl,Progress Bar,我想构建一个小管道,允许用户选择一个文件,然后使用该文件作为输入运行几个脚本。由于其中一些脚本会运行几分钟(具体时间取决于输入文件的大小),因此我想显示一个进度条,该进度条基于此管道中已完成的脚本数量 问题是,我不知道如何根据管道的状态更新此进度条,如果您能提供帮助,我将不胜感激。我先展示我使用的文件,然后更详细地解释问题 我的html表单: <form action="main.pl" method="post" enctype="multipart/form-data">

我想构建一个小管道,允许用户选择一个文件,然后使用该文件作为输入运行几个脚本。由于其中一些脚本会运行几分钟(具体时间取决于输入文件的大小),因此我想显示一个进度条,该进度条基于此管道中已完成的脚本数量

问题是,我不知道如何根据管道的状态更新此进度条,如果您能提供帮助,我将不胜感激。我先展示我使用的文件,然后更详细地解释问题

我的html表单:

<form action="main.pl" method="post" enctype="multipart/form-data">
        <input type="file" name="fileName" />
        <input type="submit" value="Analyze" />
</form>
我发现一个很好的工作进度条,如下所示(我发布了整个文件,尽管我只需要.js部分):


http://jqueryui.com/progressbar/#label
.ui进度条{
位置:相对位置;
}
.进度标签{
位置:绝对位置;
左:50%;
顶部:4px;
字体大小:粗体;
文本阴影:1px 1px 0#fff;
}
$(函数(){
var progressbar=$(“#progressbar”),
progressLabel=$(“.progressLabel”);
progressbar.progressbar({
值:false,
更改:函数(){
progressLabel.text(progressbar.progressbar(“值”)+“%”);
},
完成:函数(){
progressLabel.text(“完成!”);
}
});
功能进展(){
var val=progressbar.progressbar(“值”)|| 0;
progressbar.progressbar(“值”,val+10);
如果(val<99){
设置超时(进度,800);
}
}
setTimeout(progress,2000);
});
加载。。。
是否有任何简单的方法可以在每次更改$progressPerc的值时将其从main.pl传递到函数progress()?如果只有一个调用,这可以使用ajax来完成,但是,我不知道如何在几个调用中使用ajax,即动态调用;“动态”是指main.pl中的perl脚本完成后,应将其报告给进度条,然后更新进度条


如果没有简单的方法做到这一点:是否可以引入一个If子句,每隔x分钟(使用setTimeout)检查main.pl中这些perl脚本生成的输出文件是否存在,如果存在,则更新进度条,如果没有,则等待更长时间?如果是这样,它将如何实施?

自从我提出这个问题以来,差不多一个月过去了,但没有给出答案。因此,我现在发布我的一篇文章,它是基于这个SuiteisBlacknot的评论

虽然没有那么详细,但它可以作为一个关于如何连接Perl、HTML、Javascript/Ajax和JSON的最小示例。也许这有助于人们开始讨论这个话题

如果要运行此代码,只需将index.html文件复制到html目录(例如/var/www/html),将perl脚本复制到cgi-bin目录(例如/var/www/cgi-bin)。确保这些perl脚本是可执行的!在我下面的代码中,cgi目录位于/var/www/cgi-bin/ajax/stackCGI-请相应地更改它

管道的状态将写入一个文件,然后每隔1秒读取一次,更新进度条并显示有关当前状态的消息。管道中单个步骤的持续时间由Perl的sleep函数表示

文件如下所示

欢迎任何意见和改进

index.html:

<!DOCTYPE html>
 <html>
    <head>
        <title>Test</title> 
        <meta charset='utf-8' />
        <link rel="stylesheet" href="http://code.jquery.com/ui/1.11.3/themes/smoothness/jquery-ui.css">
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
        <script src="http://code.jquery.com/ui/1.11.3/jquery-ui.js"></script>
        <style>
           .ui-progressbar {
               position: relative;
           }
           .progress-label {
              position: absolute;
              left: 50%;

              font-weight: bold;
              text-shadow: 1px 1px 0 #fff;
           }
        </style>
<script>
        var progressVal = 0;

        function get_progress() //get_progress();
        {   

            $.ajax({
                    type: 'POST',
                    url: '/cgi-bin/ajax/stackCGI/readFromFileJson.pl',

                    success: function( res ) {

                                                $('#progressPerc').append(' ' + res.progressSummary.progress);
                                                $('#progressMessage').html('status of pipeline: ' + res.progressSummary.progressMessage);
                                                $('.progress-label').html(res.progressSummary.progress + '%');
                                                progressVal = parseFloat(res.progressSummary.progress);
                                                $( "#progressbar" ).progressbar({
                                                    value: progressVal

                                                });

                                            }
            }); 
            if (progressVal < 100){ //pipeline has not finished yet
                setTimeout(get_progress, 1000); //call the function each second every second to get a status update
            }
            else { //pipeline has finished
                $('.progress-label').html('100%');
                alert("pipeline has finished! your results can be found in path/to/files. an e-mail has been sent to user@provider.com");
            }

        }
        function start_pipeline()
        {
            $.ajax({
                    type: 'POST',
                    url: '/cgi-bin/ajax/stackCGI/pipeline.pl',
                    data: { 'fileAnalysis': $('#myFile').val() },
                    success: function(res) {
                                                //add your success function here

                                            },
                    error: function() {alert("pipeline has not started!");}
            });


        }

    </script>
</head>
<body>

    file name: <input type='text' id='myFile'/>
    <button onclick='start_pipeline();get_progress();' >Analyze now</button>
    <div id="progressbar"><div class="progress-label"></div></div>
    <div id="progressMessage"></div>
    <div id="progressPerc">status of pipeline in percent (in this example the function get_progress is called every second): </div>

</body>
readFromFileJson.pl:

#!/usr/bin/perl

use strict;
use warnings;

use JSON;
use CGI;
my $q = new CGI;

#create a file where the progress is reported to
#make sure you have the appropriate permissions to do this 
my $filename = '/var/www/cgi-bin/ajax/stackCGI/progressReport.txt'; #change the directory!
open(my $fh, '<:encoding(UTF-8)', $filename) or die "Could not open file '$filename' $!";

print $q->header('application/json;charset=UTF-8'); #output will be returned in JSON format

my @progressReport = split(/\t/,<$fh>); #file is tab separated
my %progressHash;
$progressHash{"progress"} = $progressReport[0]; 
$progressHash{"progressMessage"} = $progressReport[1];

#convert hash to JSON format
my $op = JSON -> new -> utf8 -> pretty(1);
my $output = $op -> encode({
    progressSummary => \%progressHash
});
print $output;
#/usr/bin/perl
严格使用;
使用警告;
使用JSON;
使用CGI;
my$q=新的CGI;
#创建一个向其报告进度的文件
#确保您具有执行此操作的适当权限
my$filename='/var/www/cgi-bin/ajax/stackCGI/progressReport.txt'#更改目录!

打开(我的$fh,'一个解决方案:将当前进度写入会话文件,这样不同的用户就不会践踏彼此的数据。创建另一个Perl脚本,读取会话文件并在JSON对象中返回当前进度。定期向该Perl脚本发送AJAX请求以检查进度。有趣的想法,非常感谢!让我们看看是什么原因呃我把这件事做完了。。。
<!DOCTYPE html>
 <html>
    <head>
        <title>Test</title> 
        <meta charset='utf-8' />
        <link rel="stylesheet" href="http://code.jquery.com/ui/1.11.3/themes/smoothness/jquery-ui.css">
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
        <script src="http://code.jquery.com/ui/1.11.3/jquery-ui.js"></script>
        <style>
           .ui-progressbar {
               position: relative;
           }
           .progress-label {
              position: absolute;
              left: 50%;

              font-weight: bold;
              text-shadow: 1px 1px 0 #fff;
           }
        </style>
<script>
        var progressVal = 0;

        function get_progress() //get_progress();
        {   

            $.ajax({
                    type: 'POST',
                    url: '/cgi-bin/ajax/stackCGI/readFromFileJson.pl',

                    success: function( res ) {

                                                $('#progressPerc').append(' ' + res.progressSummary.progress);
                                                $('#progressMessage').html('status of pipeline: ' + res.progressSummary.progressMessage);
                                                $('.progress-label').html(res.progressSummary.progress + '%');
                                                progressVal = parseFloat(res.progressSummary.progress);
                                                $( "#progressbar" ).progressbar({
                                                    value: progressVal

                                                });

                                            }
            }); 
            if (progressVal < 100){ //pipeline has not finished yet
                setTimeout(get_progress, 1000); //call the function each second every second to get a status update
            }
            else { //pipeline has finished
                $('.progress-label').html('100%');
                alert("pipeline has finished! your results can be found in path/to/files. an e-mail has been sent to user@provider.com");
            }

        }
        function start_pipeline()
        {
            $.ajax({
                    type: 'POST',
                    url: '/cgi-bin/ajax/stackCGI/pipeline.pl',
                    data: { 'fileAnalysis': $('#myFile').val() },
                    success: function(res) {
                                                //add your success function here

                                            },
                    error: function() {alert("pipeline has not started!");}
            });


        }

    </script>
</head>
<body>

    file name: <input type='text' id='myFile'/>
    <button onclick='start_pipeline();get_progress();' >Analyze now</button>
    <div id="progressbar"><div class="progress-label"></div></div>
    <div id="progressMessage"></div>
    <div id="progressPerc">status of pipeline in percent (in this example the function get_progress is called every second): </div>

</body>
#!/usr/bin/perl

use strict;
use warnings;

use CGI;
my $q = new CGI;

print $q->header('text/plain'); #needed! otherwise the ajax call in start_pipeline returns the error message

my $fileForAnalysis = $q -> param('fileAnalysis'); 

#create a file where the progress is reported to
#make sure you have the appropriate permissions to do this
my $filename = '/var/www/cgi-bin/ajax/stackCGI/progressReport.txt'; #change the directory!
my $fh; #file handler
my $number; #progress of pipeline in percent
my $message; #progress of pipeline

$number = 0;
$message = 'pipeline has startet successfully! Your file '.$fileForAnalysis.' is now processed.';
open($fh, '>', $filename) or die "Could not open file '$filename' $!";
print $fh $number."\t".$message;
close $fh;

sleep(3); #first program is running
$number = 10; #progress of pipeline in percent. as we have 4 programs in this pipeline it could also be 25 or whatever
$message = 'first program has finished';
open($fh, '>', $filename) or die "Could not open file '$filename' $!";
print $fh $number."\t".$message;
close $fh;

sleep(5); #second program is running
$number = 20;
$message = 'second program has finished';
open($fh, '>', $filename) or die "Could not open file '$filename' $!";
print $fh $number."\t".$message;
close $fh;

sleep(5); #third program is running
$number = 42;
$message = 'third program has finished';
open($fh, '>', $filename) or die "Could not open file '$filename' $!";
print $fh $number."\t".$message;
close $fh;

sleep(5); #fourth program is running
$number = 100;
$message = 'pipeline has finished';
open($fh, '>', $filename) or die "Could not open file '$filename' $!";
print $fh $number."\t".$message;
close $fh;
#!/usr/bin/perl

use strict;
use warnings;

use JSON;
use CGI;
my $q = new CGI;

#create a file where the progress is reported to
#make sure you have the appropriate permissions to do this 
my $filename = '/var/www/cgi-bin/ajax/stackCGI/progressReport.txt'; #change the directory!
open(my $fh, '<:encoding(UTF-8)', $filename) or die "Could not open file '$filename' $!";

print $q->header('application/json;charset=UTF-8'); #output will be returned in JSON format

my @progressReport = split(/\t/,<$fh>); #file is tab separated
my %progressHash;
$progressHash{"progress"} = $progressReport[0]; 
$progressHash{"progressMessage"} = $progressReport[1];

#convert hash to JSON format
my $op = JSON -> new -> utf8 -> pretty(1);
my $output = $op -> encode({
    progressSummary => \%progressHash
});
print $output;