Leser: 22
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
#!/usr/bin/perl -w # Module die benötigt werden use strict; use CGI::Carp qw(fatalsToBrowser); use CGI; use DBI; use upload_functions; # lokale Datendeklaration my $cgi; my $userid; my $uploadid; my $uploadfile; my $filesize; my $database; my $sql; my $presql; my %get_params; my $filename; my $imagename; my $filetype; my $filehandle; my $data; # Programm ---------------------------------------------------------------------------------- # Datenbankverbindung aufbauen $database = DBI->connect( "dbi:mysql:***", "***", "***" ) || die "Database connection not made: $DBI::errstr"; # Hole Parameter %get_params = parse_query_string($ENV{'QUERY_STRING'}); # 1. Schritt: Speichern der Dateigröße in Datenbank ######################################### # Hole Userid und Uploadid wenn vorhanden $userid = $get_params{'userid'}; $uploadid = $get_params{'uploadid'}; # Dateigröße ermitteln $filesize = $ENV{'CONTENT_LENGTH'}; # Dateigröße in Datenbank speichern $sql = "UPDATE Upload SET Size = ? WHERE UploadID = ? AND UserID = ?"; $presql = $database->prepare( $sql ); $presql->execute($filesize, $uploadid, $userid); $presql->finish(); # 2. Schritt: Lege benötigte Ordner an ###################################################### # Wechsel ins tempUploads-Verzeichnis chdir("../tempUploads"); # Erstelle Userverzeichnis, falls noch nicht vorhanden if(!-d $userid){ # Userverzeichnis existiert noch nicht -> Anlegen mkdir($userid, 0777); } # Wechsel ins Userverzeichnis chdir($userid); # Erstelle Verzeichnis zu Uploadid -> das darf es definitv noch nicht geben! mkdir($uploadid, 0777); # Wechsel ins Uploadidverzeichnis chdir($uploadid); # 3. Schritt: Lege Datei ins Verzeichnis #################################################### # Lade CGI-Objekt und setzte maximale Uploadgröße $cgi = new CGI; $cgi::POST_MAX = 100000000; # Hole Dateihandle $filehandle = $cgi->upload("uploadfile"); # Dateinamen erstellen $filename= $uploadid . '_org'; ($imagename,$filetype) = split(/\./, $filehandle); $filename = $filename.".".$filetype; # Datei ins Verzeichnis schreiben open UPLOADFILE, ">$filename" or die 'Fehler beim Schreiben der Datei'; # Binmode für Upload festlegen binmode $filehandle; binmode uploadfile; # Datei mittels while durchlaufen... while ( read $filehandle,$data,1024 ) { # ... und schreiben print UPLOADFILE $data; } # Datei schließen close UPLOADFILE; close($filehandle); # Zugriffsrechte setzen chmod(0777, $filename); # 4. Schritt: Verbuche den Uploaderfolg in Datenbank ######################################## $sql = "UPDATE Upload SET Uploaded = 1 WHERE UploadID = ? AND UserID = ?"; $presql = $database->prepare( $sql ); $presql->execute($uploadid, $userid); $presql->finish(); $database->disconnect(); # 5. Schritt: Weiterleitung ################################################################# my $url = "../index.php"; print "Location: $url\n\n"; exit;
1
2
3
4
5
6
7
$q = CGI->new(\&hook [,$data [,$use_tempfile]]);
sub hook
{
my ($filename, $buffer, $bytes_read, $data) = @_;
print "Read $bytes_read bytes of $filename\n";
}
2010-08-08T17:45:55 Paulaner[...]
Objekt zu CGI erzeugen ist mir noch klar, aber nicht so ganz, was du mit dem Hook als Konstruktorparameter meinst.
Quote[...]
Was meinst du mit eine Antwort für den Client erzeugen? Mit Print?
Quote[...]
Wie kann ich beiflussen ob die Daten gepuffert werden oder nicht?
Quote[...]
Zum letzten Punkt. Im Moment muss ich nur pro "Status holen" einmal auf die Datenbank zugreifen und die gesamte Größe zu holen. Wenn ich die tatsächlichen Fortschritt auch noch speichern wollte, müsste dies ja im PERL Script während des Uploads passieren. Wäre das schneller?
Quote[...]
Oh man... da hab ich mir was zugemutet. Wer hätte gedacht, dass das so kompliziert ist.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
#!/usr/bin/env perl use 5.012; use warnings; use constant { DB_URI => 'dbi:SQLite:dbname=/tmp/uploader.db', UPLOAD_DIR => '/tmp/uploader', MAX_UPLOAD_SIZE => 1232896, # 1 MiB }; use DBI; use CGI; use CGI::Carp qw(fatalsToBrowser); use File::Temp qw(tempdir); use File::Spec::Functions qw(catfile); # Initialize database connection and prepare statements. my $db = DBI->connect(DB_URI, { RaiseError => 1, PrintError => 0}); my %statements = ( new_upload => $db->prepare(<<EOS), INSERT INTO Uploads (dir, user, received, total) VALUES (?, NULL, 0, ?); EOS upload_received => $db->prepare(<<EOS), UPDATE Uploads SET received = received + ? WHERE dir = ?; EOS upload_complete => $db->prepare(<<EOS), UPDATE Uploads SET user = ?, total = received WHERE dir = ?; EOS ); # Initialize CGI context. $CGI::POST_MAX = MAX_UPLOAD_SIZE; my $cgi = CGI->new(\&process_upload, undef, 0) or die "Failed to create CGI context"; # Processor of uploaded data. my $dropdir; my %uploads; sub process_upload { my ($name, $buffer, $nbytes) = @_; warn "$name: $nbytes"; my $target = $uploads{$name}; unless (defined($target)) { unless (defined($dropdir)) { $dropdir = tempdir('upload.XXXXXXXX', DIR => UPLOAD_DIR) or die "Failed to create drop directory: $!"; $statements{new_upload}->execute($dropdir, $ENV{CONTENT_LENGTH}); $statements{new_upload}->finish(); } my $sane = $name; $sane =~ s/^[._]+/_/g; $sane =~ s/[^-._0-9A-Za-z]/_/g; open($target, '>:raw', catfile($dropdir, $sane)) or die "Failed to open upload target for '$name': $!"; $uploads{$name} = $target; } syswrite($target, $buffer, $nbytes) or die "Write error during upload of '$name': $!"; $statements{upload_received}->execute($nbytes, $dropdir); $statements{upload_received}->finish(); } # Finish the uploads and generate a response page. # Note that we cannot determine the value of the "user" parameter earlier, # since the client may actually send it as part of the post data and after # the uploaded files! my $user = $cgi->param('user'); print $cgi->header('text/plain'); say "Uploads for ".($user // 'unknown user')." finished:"; while (my ($name, $target) = each(%uploads)) { close($target) or die "Failed to close upload target for '$name': $!"; say " * $name"; } # Write final status into the database. if (defined($dropdir)) { # In a real application the user id should be validated somehow. $statements{upload_complete}->execute($user, $dropdir); $statements{upload_complete}->finish(); } # Close database connection. $db->disconnect();
2010-08-08T20:03:38 pqdas einzige problem des upload-hooks ist jedoch, dass zu dem zeitpunkt, wenn dieser aufgerufen wird, das CGI-objekt noch nicht da ist und man somit im prinzip keinen zugriff auf die weiteren uebergebenen parameter hat. [...]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
use CGI; # Parse query string only: my $cgi = CGI->new($ENV{QUERY_STRING}); # Extract relevant parameters: my ($query, $params) = map { $cgi->param($_) } qw(query params); # Upgrade to full CGI context and process uploads: $cgi = CGI->new(\&upload_handler, undef, 0); # Handle upload data: sub upload_handler { my ($name, $buffer, $nbytes) = @_; # ... do something ... }
1 2
if($TempFile::TMPDIRECTORY){ $TempFile::TMPDIRECTORY = $gv_tempdirpath; } elsif($CGITempFile::TMPDIRECTORY){ $CGITempFile::TMPDIRECTORY = $gv_tempdirpath; }
2010-08-08T14:21:11 Paulaner[code=perl][...]
# Hole Parameter
%get_params = parse_query_string($ENV{'QUERY_STRING'});
[...]
# Hole Userid und Uploadid wenn vorhanden
$userid = $get_params{'userid'};
$uploadid = $get_params{'uploadid'};
[...]
# Wechsel ins tempUploads-Verzeichnis
chdir("../tempUploads");
[...]
# Wechsel ins Userverzeichnis
chdir($userid);
[...]
# Wechsel ins Uploadidverzeichnis
chdir($uploadid);
[...]