Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [perl] pasek postępu uploadu plików
yarek12
post
Post #1





Grupa: Zarejestrowani
Postów: 127
Pomógł: 0
Dołączył: 5.08.2010

Ostrzeżenie: (10%)
X----


Witam,
Już od dłuższego czasu próbuję napisać pasek postępu, przepatrzyłem praktycznie cały internet i wszystkie możliwości, jednak nie znalazłem żadnego działającego rozwiązania.

Więc postanowiłem spróbować z perlem, oto mój kod uploadu:

  1. #!/usr/bin/perl -w
  2.  
  3. use strict;
  4.  
  5. use warnings;
  6. use CGI;
  7. use CGI::Carp qw(fatalsToBrowser);
  8.  
  9. my $q = new CGI();
  10.  
  11.  
  12. # Handle actions.
  13. if ($q->param('action') eq "upload") {
  14. # They just submitted the form and are sending a file.
  15.  
  16. my $filename = $q->param('file');
  17. my $handle = $q->upload('file');
  18. $filename =~ s/(?:\\|\/)([^\\\/]+)$/$1/g;
  19.  
  20. # File size.
  21.  
  22. my $size = (-s $handle);
  23.  
  24. # This session ID would be randomly generated for real.
  25. my $sessid = 'my-session';
  26.  
  27. # Create the session file.
  28.  
  29. open (CREATE, ">./sessions/$sessid") or die "can't create session: $!";
  30. print CREATE "size=$size&file=$filename";
  31. close (CREATE);
  32.  
  33. # Start receiving the file.
  34.  
  35. open (FILE, ">./files/$filename");
  36. while (<$handle>) {
  37. }
  38. close (FILE);
  39.  
  40. # Delete the session.
  41.  
  42. unlink("./sessions/$sessid");
  43.  
  44. # Done.
  45. print $q->header();
  46. print "Thank you for your file. <a href=\"files/$filename\">Here it is again</a>.";
  47. }
  48.  
  49. elsif ($q->param('action') eq "progress") {
  50. # They're checking up on their progress; get their sess ID.
  51. my $sessid = $q->param('session') || 'my-session';
  52. print $q->header(type => 'text/plain');
  53.  
  54. # Does it exist?
  55.  
  56. if (!-f "./sessions/$sessid") {
  57. print "error:Your session was not found.";
  58. exit(0);
  59. }
  60.  
  61. # Read it.
  62.  
  63. open (READ, "./sessions/$sessid");
  64. my $line = <READ>;
  65. close (READ);
  66.  
  67. # Get their file size and name.
  68.  
  69. my ($size,$name) = $line =~ /^size=(\d+)&file=(.+?)$/;
  70.  
  71. # How much was downloaded?
  72.  
  73. my $downloaded = -s "./files/$name";
  74.  
  75. # Calculate a percentage.
  76. my $percent = 0;
  77. if ($size > 0) {
  78. $percent = ($downloaded / $size) * 100;
  79. $percent =~ s/\.(\d)\d+$/.$1/g;
  80. }
  81.  
  82. # Print some data for the JS.
  83.  
  84. print "okay:size=$size&received=$downloaded&percent=$percent";
  85. exit(0);
  86. }
  87. else {
  88. die "unknown action";
  89. }


Serwer zwraca jednak następujący błąd: couldn't create child process: 720003: upload.cgi


Z góry dziękuję za pomoc, bardzo mi na tym zależy, ewentualnie jeśli ktoś zna inny sposób na pasek postępu, również będę wdzięczny.
Pozdrawiam.
Go to the top of the page
+Quote Post
JohnnyB
post
Post #2





Grupa: Zarejestrowani
Postów: 76
Pomógł: 19
Dołączył: 19.01.2010

Ostrzeżenie: (0%)
-----


właśnie niedawno zrobiłem sobie fajny paseczek, tylko nie w Perlu, a z wykorzystaniem APC - działa bez zarzutu, jedyny kłopot, że trzeba mieć APC na serwerze.
Go to the top of the page
+Quote Post
yarek12
post
Post #3





Grupa: Zarejestrowani
Postów: 127
Pomógł: 0
Dołączył: 5.08.2010

Ostrzeżenie: (10%)
X----


Próbowałem APC, jednak nie działało, możesz mi coś poradzić? Jak się do tego zabrać, może znasz jakiś tutorial?


Ten post edytował yarek12 8.11.2011, 19:36:15
Go to the top of the page
+Quote Post
JohnnyB
post
Post #4





Grupa: Zarejestrowani
Postów: 76
Pomógł: 19
Dołączył: 19.01.2010

Ostrzeżenie: (0%)
-----


sprawdź jakie masz ustawienia (w plikach konfiguracyjnych lub za pomocą phpinfo() ).
Interesuje nas sekcja APC, w szczególności ustawienia dotyczące opcji rfc1867. Poniżej podaję wartości jakie są u mnie:

apc.enabled On

apc.rfc1867 On
apc.rfc1867_freq 0
apc.rfc1867_name APC_UPLOAD_PROGRESS
apc.rfc1867_prefix upload_

sprawdź i napisz co jest u ciebie, będzie to później potrzebne.

Ten post edytował JohnnyB 8.11.2011, 20:05:23
Go to the top of the page
+Quote Post
yarek12
post
Post #5





Grupa: Zarejestrowani
Postów: 127
Pomógł: 0
Dołączył: 5.08.2010

Ostrzeżenie: (10%)
X----


apc.enabled On On
apc.rfc1867 On On
apc.rfc1867_freq 0 0
apc.rfc1867_name APC_UPLOAD_PROGRESS APC_UPLOAD_PROGRESS
apc.rfc1867_prefix upload_ upload_

Widać ustawienia mamy takie same.
Go to the top of the page
+Quote Post
JohnnyB
post
Post #6





Grupa: Zarejestrowani
Postów: 76
Pomógł: 19
Dołączył: 19.01.2010

Ostrzeżenie: (0%)
-----


ok, no to lecimy dalej:
  1. <?php
  2. if(isset($_GET['progress'])) {
  3. header('Expires: Tue, 08 Oct 1991 00:00:00 GMT');
  4. header('Cache-Control: no-cache, must-revalidate');
  5. $status=apc_fetch("upload_$_GET[progress]");
  6. if(!$status) die(0);
  7. echo round($status['current']/$status['total']*100);
  8. exit();
  9. }

to właśnie sedno programu - procent przesłania sprawdzamy za pomocą funkcji apc_fetch, jako musimy podać nazwę naszego uploadu - w powyższym przykładzie będzie ona przesyłana poprzez GET w zmiennej o nazwie 'progress'. Nazwa musi być poprzedzona przedrostkiem zdefiniowanym w apc.rfc1867_prefix (u nas 'upload_'). Zwracaną wartość będziemy okresowo pobierać poprzez AJAX.

  1. $message='';
  2. if($_FILES) {
  3. if($_FILES['plik']['error']==UPLOAD_ERR_OK) {
  4. $path='/tmp/';
  5. $path.=basename($_FILES['plik']['name']);
  6. if(move_uploaded_file($_FILES['plik']['tmp_name'],$path))
  7. $message='Plik przesłany poprawnie.';
  8. else
  9. $message='Błąd podczas kopiowania pliku';
  10. } else $message="Błąd podczas przesyłania pliku: ".$_FILES['plik']['error'];
  11. die($message);
  12. }
  13. ?>

To klasyczny fragment obsługujący przesyłanie pliku.

  1. <meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
  2. <script type='text/javascript'>
  3. var oReq=new XMLHttpRequest();
  4.  
  5. function getProgress() {
  6. oReq.open('GET','test.php?progress=pasek_1',true);
  7. oReq.onreadystatechange=updateProgress
  8. oReq.send(null);
  9. }
  10.  
  11. function updateProgress() {
  12. if(oReq.readyState!=4 || oReq.status!=200) return;
  13. var progress=oReq.responseText;
  14. document.getElementById('procent').innerHTML=progress+'%';
  15. if(progress<100) setTimeout('getProgress()',500);
  16. }
  17. </head>

Pierwsza funkcja pobiera procent wysłania pliku przez AJAX, druga ustawia na tej podstawie zawartość diva.

  1. <?php echo $message; ?>
  2. <div id='procent'></div>
  3. <form name='f1' method='POST' action='' enctype='multipart/form-data'
  4. onSubmit='setTimeout("getProgress()",500)' target='upload_frame'>
  5. <input type='hidden' name='APC_UPLOAD_PROGRESS' value='pasek_1' />
  6. Plik: <input type='file' name='plik' /><br>
  7. <input type='submit' value='Wyślij' />
  8. </form>
  9.  
  10. <a href=''>Odśwież</a>
  11. <iframe style='display:block' name='upload_frame'></iframe>
  12. </body>
  13. </html>

Na koniec właściwa część do wysłania pliku - jak widać tworzymy specjalne pole o nazwie określonej w apc.rfc1867_name (APC_UPLOAD_PROGRESS) i ustawiamy dowolną wartość - to co tu wpiszemy musimy potem przesłać do funkcji apc_fetch.

To wszystko - wszystkie kody mogą być w jednym pliku, w moim przypadku nazywa się on test.php (ta nazwa używana w wywołaniu AJAX-owym). W przykładzie wprawdzie postęp jest podawany liczbowo, ale myślę, że dorobienie do tego paska nie będzie dużym problemem.
Aha, warto jeszcze pamiętać o ustawieniu odpowiednio dużej wartości post_max_size w php.ini.
Go to the top of the page
+Quote Post
yarek12
post
Post #7





Grupa: Zarejestrowani
Postów: 127
Pomógł: 0
Dołączył: 5.08.2010

Ostrzeżenie: (10%)
X----


Chyba coś robię nie tak, apc widać działa bo żaden błąd nie wyskoczył, efekt jest taki że nie uploaduje nawet żadnego pliku, przeładowuje tylko stronę a do ramki wczytują całą stronę od nowa.
Nie wiem czy dobrze zrozumiałem kod, zobacz jak to posklejałem:


apc.php:
  1. <html>
  2. <head>
  3. <meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
  4. <script type='text/javascript'>
  5. var oReq=new XMLHttpRequest();
  6.  
  7. function getProgress() {
  8. oReq.open('GET','test.php?progress=pasek_1',true);
  9. oReq.onreadystatechange=updateProgress
  10. oReq.send(null);
  11. }
  12.  
  13. function updateProgress() {
  14. if(oReq.readyState!=4 || oReq.status!=200) return;
  15. var progress=oReq.responseText;
  16. document.getElementById('procent').innerHTML=progress+'%';
  17. if(progress<100) setTimeout('getProgress()',500);
  18. }
  19. </script>
  20. </head>
  21. <body>
  22. <?php echo $message; ?>
  23. <div id='procent'></div>
  24. <form name='f1' method='POST' action='' enctype='multipart/form-data'
  25. onSubmit='setTimeout("getProgress()",500)' target='upload_frame'>
  26. <input type='hidden' name='APC_UPLOAD_PROGRESS' value='pasek_1' />
  27. Plik: <input type='file' name='plik' /><br>
  28. <input type='submit' value='Wyślij' />
  29. </form>
  30.  
  31. <a href=''>Odśwież</a>
  32. <iframe style='display:block' name='upload_frame'></iframe>
  33. </body>
  34. </html>


test.php:
  1. <?php
  2. if(isset($_GET['progress'])) {
  3. header('Expires: Tue, 08 Oct 1991 00:00:00 GMT');
  4. header('Cache-Control: no-cache, must-revalidate');
  5. $status=apc_fetch("upload_$_GET[progress]");
  6. if(!$status) die(0);
  7. echo round($status['current']/$status['total']*100);
  8. exit();
  9. }
  10. $message='';
  11. if($_FILES) {
  12. if($_FILES['plik']['error']==UPLOAD_ERR_OK) {
  13. $path='/tmp/';
  14. $path.=basename($_FILES['plik']['name']);
  15. if(move_uploaded_file($_FILES['plik']['tmp_name'],$path))
  16. $message='Plik przesłany poprawnie.';
  17. else
  18. $message='Błąd podczas kopiowania pliku';
  19. } else $message="Błąd podczas przesyłania pliku: ".$_FILES['plik']['error'];
  20. die($message);
  21. }
  22. ?>
Go to the top of the page
+Quote Post
JohnnyB
post
Post #8





Grupa: Zarejestrowani
Postów: 76
Pomógł: 19
Dołączył: 19.01.2010

Ostrzeżenie: (0%)
-----


to wszystko (cały kod) powinno być w jednym pliku o nazwie test.php, przy czym kod PHP powinien być pierwszy. Czyli wstaw plik, który oznaczyłeś apc.php na końcu do test.php.
Go to the top of the page
+Quote Post
yarek12
post
Post #9





Grupa: Zarejestrowani
Postów: 127
Pomógł: 0
Dołączył: 5.08.2010

Ostrzeżenie: (10%)
X----


teraz plik się wysyła, czyli jest ok, ale wyświetla się tylko % bez żadnej wartośći
Go to the top of the page
+Quote Post
JohnnyB
post
Post #10





Grupa: Zarejestrowani
Postów: 76
Pomógł: 19
Dołączył: 19.01.2010

Ostrzeżenie: (0%)
-----


podobno czasami funkcje apc_fetch lepiej działa jeśli parametr apc.rfc1867_freq na jakąś wartość, np. apc.rfc1867_freq = 10k (po zmianie pamiętaj o przeładowaniu Apache). Jeśli to nie pomoże, to niestety, nie mam więcej pomysłów.
Go to the top of the page
+Quote Post
yarek12
post
Post #11





Grupa: Zarejestrowani
Postów: 127
Pomógł: 0
Dołączył: 5.08.2010

Ostrzeżenie: (10%)
X----


Powiedz mi a do jakiego folderu jest uploadowany plik, bo ja nic nie zmieniałem kodzie, może to ma znaczenie.
Go to the top of the page
+Quote Post
JohnnyB
post
Post #12





Grupa: Zarejestrowani
Postów: 76
Pomógł: 19
Dołączył: 19.01.2010

Ostrzeżenie: (0%)
-----


Docelowo pliki kopiowane są tutaj:
  1. $path='/tmp/';

ale to raczej nie powinno mieć wpływu, bo odbywa się już po zakończeniu przesyłania pliku. W trakcie uploadu pliki są zapisywane do domyślnego katalogu tymczasowego serwera. Można to zmienić ustawiając odpowiednio parametr 'upload_tmp_dir' w php.ini, ale nie sądzę żeby to był problem, raczej coś z samym APC.
Wraz z rozszerzeniem ACP jest instalowany plik apc.php (u mnie był on w katalogu /usr/share/php/apc/apc.php), jeśli nie masz to poszukaj w necie i wrzuć gdzieś na serwer - po zalogowaniu zobaczysz wiele szczegółowych danych, w szczególności na zakładce 'User cache entries' powinieneś widzieć zmienną 'upload_pasek_1' wraz z informacjami o niej.
Sprawdź też jaką masz wersję APC - u mnie jest 3.1.7, może spróbuj wgrać nowszą, jeśli masz taką możliwość.

Ten post edytował JohnnyB 12.11.2011, 11:05:20
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 21.08.2025 - 09:19