jQuery 和 perl:进度条基于 "pipeline file" 的状态,动态 ajax
jQuery and perl: progress bar based on state of "pipeline file", dynamic ajax
我想构建一个小型管道,允许用户选择一个文件,然后 运行s 多个脚本使用该文件作为输入。由于其中一些脚本 运行 持续了几分钟(确切时间取决于输入文件的大小),我想显示一个进度条,该进度条基于已完成此管道的脚本数量。
问题是我不知道如何根据管道的状态更新此进度条,希望得到一些帮助。我先展示我使用的文件,然后更详细地解释问题。
我的html表格:
<form action="main.pl" method="post" enctype="multipart/form-data">
<input type="file" name="fileName" />
<input type="submit" value="Analyze" />
</form>
管道脚本main.pl:
#!/usr/bin/perl
use CGI;
use strict;
#use warnings;
my $q = CGI->new;
my $fileName = $q->param('fileName');
my $progressPerc = 0;
my $numJobs = 3; #in actual script much more
my $count = 1;
system('perl', './file1.pl', $fileName);
$progressPerc = $count/$numJobs*100;
#here I want to pass $progressPerc to the progress bar
$count += 1;
system('perl', './file2.pl', $fileName);
$progressPerc = $count/$numJobs*100;
#here I want to pass $progressPerc to the progress bar
$count += 1;
system('perl', './file3.pl', $fileName);
$progressPerc = $count/$numJobs*100;
#here I want to pass $progressPerc to the progress bar
我在 http://jqueryui.com/progressbar/#label 上找到了一个很好的工作进度条,如下所示(我 post 整个文件,尽管我只需要 .js 部分):
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>http://jqueryui.com/progressbar/#label</title>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script src="http://code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<style>
.ui-progressbar {
position: relative;
}
.progress-label {
position: absolute;
left: 50%;
top: 4px;
font-weight: bold;
text-shadow: 1px 1px 0 #fff;
}
</style>
<script>
$(function() {
var progressbar = $( "#progressbar" ),
progressLabel = $( ".progress-label" );
progressbar.progressbar({
value: false,
change: function() {
progressLabel.text( progressbar.progressbar( "value" ) + "%" );
},
complete: function() {
progressLabel.text( "Complete!" );
}
});
function progress() {
var val = progressbar.progressbar( "value" ) || 0;
progressbar.progressbar( "value", val + 10 );
if ( val < 99 ) {
setTimeout( progress, 800 );
}
}
setTimeout( progress, 2000 );
});
</script>
</head>
<body>
<div id="progressbar"><div class="progress-label">Loading...</div></div>
</body>
</html>
有什么简单的方法可以在每次更改其值时将 $progressPerc 从 main.pl 传递给函数 progress() 吗?如果只有一个电话,这可以使用 ajax 来完成,但是,我不知道如何使用 ajax 进行多个电话,即动态地; 'dynamic' 我的意思是,一旦 main.pl 中的 perl 脚本完成,这应该报告给进度条,然后更新进度条。
如果没有简单的方法来做到这一点:是否可以引入一个 if 子句,每隔 x 分钟检查一次(使用 setTimeout)main.pl 中这些 perl 脚本生成的输出文件是否存在,如果存在的话,进度条已更新,如果没有,是否需要等待更长时间?如果是这样,它将如何实施?
问这个问题已经快一个月了,但没有出现答案。因此,我现在 post 我的一个基于 ThisSuitIsBlackNot 的评论。
虽然没有那么详细,但它可以作为一个关于如何连接 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 的睡眠函数表示。
文件如下。
欢迎任何意见和改进!
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>
pipeline.pl:
#!/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;
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;
我想构建一个小型管道,允许用户选择一个文件,然后 运行s 多个脚本使用该文件作为输入。由于其中一些脚本 运行 持续了几分钟(确切时间取决于输入文件的大小),我想显示一个进度条,该进度条基于已完成此管道的脚本数量。
问题是我不知道如何根据管道的状态更新此进度条,希望得到一些帮助。我先展示我使用的文件,然后更详细地解释问题。
我的html表格:
<form action="main.pl" method="post" enctype="multipart/form-data">
<input type="file" name="fileName" />
<input type="submit" value="Analyze" />
</form>
管道脚本main.pl:
#!/usr/bin/perl
use CGI;
use strict;
#use warnings;
my $q = CGI->new;
my $fileName = $q->param('fileName');
my $progressPerc = 0;
my $numJobs = 3; #in actual script much more
my $count = 1;
system('perl', './file1.pl', $fileName);
$progressPerc = $count/$numJobs*100;
#here I want to pass $progressPerc to the progress bar
$count += 1;
system('perl', './file2.pl', $fileName);
$progressPerc = $count/$numJobs*100;
#here I want to pass $progressPerc to the progress bar
$count += 1;
system('perl', './file3.pl', $fileName);
$progressPerc = $count/$numJobs*100;
#here I want to pass $progressPerc to the progress bar
我在 http://jqueryui.com/progressbar/#label 上找到了一个很好的工作进度条,如下所示(我 post 整个文件,尽管我只需要 .js 部分):
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>http://jqueryui.com/progressbar/#label</title>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script src="http://code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<style>
.ui-progressbar {
position: relative;
}
.progress-label {
position: absolute;
left: 50%;
top: 4px;
font-weight: bold;
text-shadow: 1px 1px 0 #fff;
}
</style>
<script>
$(function() {
var progressbar = $( "#progressbar" ),
progressLabel = $( ".progress-label" );
progressbar.progressbar({
value: false,
change: function() {
progressLabel.text( progressbar.progressbar( "value" ) + "%" );
},
complete: function() {
progressLabel.text( "Complete!" );
}
});
function progress() {
var val = progressbar.progressbar( "value" ) || 0;
progressbar.progressbar( "value", val + 10 );
if ( val < 99 ) {
setTimeout( progress, 800 );
}
}
setTimeout( progress, 2000 );
});
</script>
</head>
<body>
<div id="progressbar"><div class="progress-label">Loading...</div></div>
</body>
</html>
有什么简单的方法可以在每次更改其值时将 $progressPerc 从 main.pl 传递给函数 progress() 吗?如果只有一个电话,这可以使用 ajax 来完成,但是,我不知道如何使用 ajax 进行多个电话,即动态地; 'dynamic' 我的意思是,一旦 main.pl 中的 perl 脚本完成,这应该报告给进度条,然后更新进度条。
如果没有简单的方法来做到这一点:是否可以引入一个 if 子句,每隔 x 分钟检查一次(使用 setTimeout)main.pl 中这些 perl 脚本生成的输出文件是否存在,如果存在的话,进度条已更新,如果没有,是否需要等待更长时间?如果是这样,它将如何实施?
问这个问题已经快一个月了,但没有出现答案。因此,我现在 post 我的一个基于 ThisSuitIsBlackNot 的评论。
虽然没有那么详细,但它可以作为一个关于如何连接 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 的睡眠函数表示。
文件如下。
欢迎任何意见和改进!
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>
pipeline.pl:
#!/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;
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;