Apache-UploadMeter
view release on metacpan or search on metacpan
lib/Apache/UploadMeter.pm view on Meta::CPAN
# of the users are going to be using the bundled JS code, or forking from
# it, meaning they already have what they need.
# The other 5% are writing from scratch; hopefully embedding into some non-
# browser based application. They most likely want XML anyway, and its
# their life that I want to make easier :-)
my $format = $req->param("format") || "XML";
my $currenttime = time();
my $starttime=$hook_cache->get($hook_id."starttime") || $currenttime;
# JSON response
if ($format=~/^json$/i) {
# Hardcode object for now. No need to require YAML or YAML::Syck as prereq
my $json=sprintf('{"meter_id":"%s","filename":"%s","finished":%d,"status":{"timestamp":%d,"start":%d,"received":%d,"total":%d}}',
$hook_id, $fname, $finished, $currenttime, $starttime, $len, $size);
$r->content_type("application/json");
$r->set_content_length(length($json));
$r->print($json) unless $r->header_only;
return Apache2::Const::OK;
}
# XML response (legacy)
# This is better done in the XSL, I think. I want to minimize Apache's work here and leave the browser to calculate the stuff. What I may eventually do is create a second XSL stylesheet which translates the "minimal" formatting into this format...
# Calculate total rate and current rate
my $lastupdatetime = $hook_cache->get($hook_id."lastupdatetime");
my $lastupdatelen = $hook_cache->get($hook_id."lastupdatelen");
my $currentrate = int (($len - $lastupdatelen) / ($currenttime - $lastupdatetime)) if ($currenttime != $lastupdatetime);
my $rate = int ($len / ($currenttime - $starttime)) if ($currenttime != $starttime);
$hook_cache->set($hook_id."lastupdatetime", $currenttime);
$hook_cache->set($hook_id."lastupdatelen", $len);
# Calculate elapsed and remaining time
my $etime = $currenttime - $starttime;
my $rtime = ($finished) ? 0 : int ($etime / $len * $size) - $etime;
# Format values for easy display
my $fsize = Number::Format::format_bytes($size, 2);
my $flen = Number::Format::format_bytes($len, 2);
my $fetime = Date::Format::time2str('%H:%M:%S', $etime, 'GMT');
my $frtime = Date::Format::time2str('%H:%M:%S', $rtime, 'GMT');
my $fcurrentrate = Number::Format::format_bytes($currentrate, 2).'/s';
my $frate = Number::Format::format_bytes($rate, 2).'/s';
# build the Refresh url
my $args=$r->args;
if ($initial_request) { $args=$args.(defined($args)?"&":"")."returned=1";}
if ($finished) {
# Cleanup the cache since we are finished
# Not needed. The hook automatically dumps values every 15 minutes for this reason. - Issac. But a purge is probably needed somewhere else for a global scale
$hook_cache->remove($hook_id."finished");
$hook_cache->remove($hook_id."len");
$hook_cache->remove($hook_id."name");
$hook_cache->remove($hook_id."size");
$hook_cache->remove($hook_id."starttime");
$hook_cache->remove($hook_id."lastupdaterate");
$hook_cache->remove($hook_id."lastupdatelen");
$hook_cache->clear;
$hook_cache->purge; #best I can do for now...
} else {
# Set a refresh header so the meter gets updated
my $uri = APR::URI->parse($r->pool, $r->uri);
$uri->scheme($ENV{HTTPS}?"https":"http");
$uri->port($r->server->port ? $r->server->port : APR::URI::port_of_scheme($uri->scheme));
$uri->path($r->uri);
$uri->hostname($r->server->server_hostname);
$uri->query($args);
$r->headers_out->add("Refresh"=>"5;url=".$uri->unparse());
}
$r->content_type('text/xml');
return Apache2::Const::OK if $r->header_only;
my $config = $r->pnotes("Apache::UploadMeter::Config");
my $meter = $config->("UploadMeter") || $r->uri;
my $xsl="$meter/styles/xml/aum.xsl";
my $xsd="$meter/styles/xml/aum.xsl";
my $out= <<EOF;
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="$xsl"?>
<APACHE_UPLOADMETER METER_ID="$hook_id" FILE="$fname" FINISHED="$finished" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="$xsd">
<RECEIVED VALUE="$len">$flen</RECEIVED>
<TOTAL VALUE="$size">$fsize</TOTAL>
<ELAPSEDTIME VALUE="$etime">$fetime</ELAPSEDTIME>
<REMAININGTIME VALUE="$rtime">$frtime</REMAININGTIME>
<RATE VALUE="$rate">$frate</RATE>
<CURRENTRATE VALUE="$currentrate">$fcurrentrate</CURRENTRATE>
</APACHE_UPLOADMETER>
EOF
$r->print($out);
return Apache2::Const::OK;
}
# Form fixup
sub uf_handler
{
my $r=shift;
$r->no_cache(1); # CRITICAL! No caching allowed!
$r->set_last_modified(time());
$r->err_headers_out->add("Expires" => Apache2::Util::ht_time($r->pool));
my $digest=Digest::SHA1::sha1_hex(time,(defined $r->subprocess_env('HTTP_HOST') ? $r->subprocess_env('HTTP_HOST') : 0),(defined $r->subprocess_env('HTTP_X_FORWARDED_FOR') ?$r->subprocess_env('HTTP_X_FORWARDED_FOR') : 0 ));
$r->pnotes("u_id"=>$digest);
return Apache2::Const::OK;
}
### Support handlers (for debugging)
# Simple response handler for displaying upload information
sub r_handler
{
my $r=shift;
my $req = APR::Request::Apache2->handle($r);
$r->no_cache(1);
my $uploads=$req->upload;
$r->content_type('text/plain');
return Apache2::Const::OK if $r->header_only;
$r->print("Results:\n");
while (my ($field, $upload) = each %$uploads) {
$r->print("Parsed upload field $field:\n\tFilename: ".$upload->upload_filename());
$r->print("\n\tSize: ".$upload->upload_size()."\n\n");
}
$r->print("Done\n");
( run in 2.185 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )