[PHP] new ZipArchive, bestanden zippen, na 8 files, fail

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hallo, ik probeer bestanden te zippen met php, en de volgende code roep ik aan per bestand (ik heb dit ook allemaal in één keer geprobeerd) dus uiteindelijk probeer ik de bestanden per stuk toe te voegen, maar na zo'n 8 of 9 bestanden aan de zip te hebben toegevoegd, worden de bestanden daarna niet meer toegevoegd, ik heb dit met gewone tekstbestanden geprobeerd dus geen extreem grote bestanden etc.

In php.ini kan ik niets van een limit vinden voor zip of iets derglijks, en de codes die ik allemaal geprobeerd heb zijn voorbeelden van de php website waar ik wel iets van een workaround die om de zoveel bestanden de close en weer open, kon vinden maar daarbij blijft het probleem hetzelfde

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    $_GET['bron'] = "../../bla/bestandsnaam.html";
    
    $doel = str_replace("../../bla/","./",$_GET['bron']);   
    
    $zip = new ZipArchive;

    if ($zip->open('./Managers.zip') === TRUE)
    {
        # Mogelijkheid 1
        $zip->addFile($_GET['bron'], $doel);
        
        # Mogelijkheid 2
        $contents = file_get_contents($_GET['bron']);
        $zip->addFromString($doel, $contents);
        
        $zip->close();
        echo "succes";
    }
    else
    {
        echo "fail";
    }

Iemand enig idee? 8)7

[ Voor 4% gewijzigd door Verwijderd op 07-07-2009 15:19 ]


Acties:
  • 0 Henk 'm!

  • Cascade
  • Registratie: Augustus 2006
  • Laatst online: 16-09 11:44
Wat voor ordegrootte bestanden hebben we het hier over? Zit je geheugenruimte voor PHP niet gewoon vol?

Als ik het goed begrijp open je steeds een bestaande zip en voegt daar inhoud aan toe?

Zou eens kijken naar:
- geheugengebruik.
- schijfruimte.
- of de content wel goed ingelezen wordt.
- uitgebreide foutcodes uit de ZipArchive class (true / false is een beetje weinig).
- eventueel de nieuwe Phar extension in PHP 5.3 (als dat een optie is).

[ Voor 5% gewijzigd door Cascade op 07-07-2009 15:22 ]


Acties:
  • 0 Henk 'm!

  • Mike2k
  • Registratie: Mei 2002
  • Laatst online: 22-08 11:59

Mike2k

Zone grote vuurbal jonge! BAM!

check ook even je max execution time...wellicht loopt 'ie daar tegen aan...

You definitely rate about a 9.0 on my weird-shit-o-meter
Chuck Norris doesn't dial the wrong number. You answer the wrong phone.


Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Is het altijd dezelfde filename waar ie op stuk gaat? zoja, probeer die eens als eerste ipv. als 8e.

Acties:
  • 0 Henk 'm!

  • winkbrace
  • Registratie: Augustus 2008
  • Laatst online: 24-08 15:17
Je zou inderdaad eens kunnen proberen het blok code in een try-catch blok te plaatsen
code:
1
2
3
4
5
6
7
8
9
try 
{ 
    << je code >>
} 
catch (Exception $e) 
{ 
    $e->getMessage(); 
    $e->getStackTrace(); 
}

[ Voor 9% gewijzigd door winkbrace op 07-07-2009 15:56 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
PHP geheugen vol?, hoe kan ik die legen of vergroten in ruimte?

Ik heb de max_execution_time op 3000,
Ik heb verschillende bestanden geprobeerd, altijd worden 8 bestanden in de zip bijgeschreven en dan geeft ie false terug.

Maar het lijkt er dus op dat het het aantal bestanden (8) als max aanhoud dan de grootte.
Het zijn allemaal gewoon tekst bestanden, dus het is geen zwaare operatie voor het geheugen lijkt me zo. Echter is het wel vreemd, omdat ik deze code dus steeds apart aanroep, per bestand wordt dan de zip even geopend en het enkele bestand erin gezet, vervolgens wordt dezelfde code weer aangeroepen en na 8 x werkt het ineens niet meer.

Ik ga nu even kijken naar Phar, maar ik vind bovenstaande ook wel intressant. :)

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb even gekeken naar de Phar extension, dat is wel heel erg intressant, ik wil namelijk mijn php-applicatie kunnen inpakken en uitpakken, ik heb deze ook al lokaal zie ik net.

Toch wel nuttig om de zip functie nog uit te zoeken voor andere doeleinden.

Acties:
  • 0 Henk 'm!

  • Cascade
  • Registratie: Augustus 2006
  • Laatst online: 16-09 11:44
Voor ZipArchive moet je de returnwaarde van de open functie eens goed bekijken.

Zie: ZipArchive::open , dat zou je meer moeten vertellen wat er nou aan de hand is...

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb even gekeken naar de error die ik terug krijg is 19 en dat zou ER_NOZIP moeten betekenen volgens een post op de php website. Maar wat betekend ER_NOZIP dan precies?

Acties:
  • 0 Henk 'm!

  • hostname
  • Registratie: April 2009
  • Laatst online: 17-09 17:56
Verwijderd schreef op dinsdag 07 juli 2009 @ 20:18:
Ik heb even gekeken naar de error die ik terug krijg is 19 en dat zou ER_NOZIP moeten betekenen volgens een post op de php website. Maar wat betekend ER_NOZIP dan precies?
Geen geldige zip file.

PHP's zip pakt door Windows gecreerde zips niet altijd goed, dus misschien ligt het daaraan?

Acties:
  • 0 Henk 'm!

  • Cascade
  • Registratie: Augustus 2006
  • Laatst online: 16-09 11:44
ER_NOZIP is letterlijk 'Not a zip archive' , inderdaad geen geldige zip file. Zie ook: PHP ZipArchive constants. Dit zou betekenen dat jouw zip bestand kapot is, en zodanig dat het niet meer op een zip file lijkt (wat best wel raar is).

Aangezien in ZipArchive de close functie pas alle wijzigingen schrijft, zou het al fout zijn bij de close voor de open die de fout terug geeft. Ik zou het hele process na die ene close kunstmatig stoppen en dan die zip file eens bekijken met zip software (WinZip / WinRar / TotalCommander) en kijken of het bestand dan al kapot is.

Zit je bestandsgrootte van de zip dicht bij de 2 GB als het gebeurt? Of nog lang niet? (wat is niet extreem tegenwoordig? :P )

Als extra kan je nog controleren of de addFile / addFromString en close functies wel succesvol zijn. Je zou verwachten dat de laatste close voor de foute open ook FALSE terug geeft (maar dan nog: reden onbekend).

Kloppen al je bestandsnamen wel? Bestaan de bestanden die toegevoegd worden aan de zip wel en hebben ze inhoud? Klopt je doel naam wel steeds?

Een bug of incompatibiliteit in de PHP ZipArchive implementatie kan ook nog eens, mee eens.

Nog een raar idee: hoe roep je dat script aan? Ik zie een _GET['bron'], ik denk: een chain van AJAX calls. Loopt het wel allemaal netjes achter elkaar? En klopt de encoding van de bestandsnamen ook?

[ Voor 8% gewijzigd door Cascade op 07-07-2009 21:04 ]


Acties:
  • 0 Henk 'm!

Verwijderd

klinkt als een concurrency probleem. 1 instance is nog aan het schrijven terwijl de andere er ook in begint te schrijven en een 3e ontdekt dat er niks meer van je zip file klopt. Dat het altijd de 8e is komt mischien door de filebuffers of waarschijnlijker je httpd settings: je file-pointer wordt per process gedeeld en als je 8 request per work-child afhandelt komt de 8e op een andere process terecht; krijgt een nieuwe pointer en ziet de rotzooi.

aangezien je $_GET gebruikt ga ik uit van een http/web omgeving.
PHP:
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
 # Er kan maar 1 session tegelijk openzijn dus dit is al een goeie lock.
 session_start();

 # Het kan nooit kwaad je variablen alvast te initializeren.
 $zipF = "./Managers.zip";
 $doel = "";
 $bron = trim($_GET["bron"]);

 try{
  # Check altijd je input, grondig.
  if((is_string($bron) !== true) OR (strlen($bron) < 1)){
   throw new Exception("Bron is niet in geldig string formaat.");
  }
  if((is_file($bron) !== true) OR (is_readable($bron) !== true)){
   throw new Exception("Bron is geen geldig bestand.");
  }

  # vraagje, probeer je hier gewoon het path weg te gooien?
  # is dit dan niet beter:
  #$doel = sprintf("./%s", basename($bron));
  $doel = str_replace("../../bla/", "./", $bron);

  # Check dat het zipArchive bestaat en leesbaar + schrijfbaar is.
  if((is_file($zipF) !== true) OR (is_readable($zipF) !== true) OR (is_writeable($zipF) !== true)){
   throw new Exception("ZipArchive does not exists or is not readable.");
  }
 
  # Creeer een nieuw leeg ZipArchive object.
  $zip  = new ZipArchive();
 
  # Letop de flags die ik heb toegevoegd, ik gok dat ZIPARCHIVE::EXCL een lock zet op de zip file
  # maar de docs zeggen niet er niet veel over. Zie ook dat ZIPARCHIVE::CREATE mist ivm bovenstaande.
  $open = $zip->open($zipF, (ZIPARCHIVE::EXCL | ZIPARCHIVE::CHECKCONS));
  if($open !== true){
   throw new Exception(sprintf("Failed to open ZipArchive. code: %u.", $open));
  }

  # Ik kies de eerste method omdat die mij minder geheugen intensief lijkt en hij is makkelijker.
  if($zip->addFile($bron, $doel) !== true){
   Throw new Exception("Failed to add file to zip Archive."); 
  }

  # En sluit de zipArchive.
  if($zip->close() !== true){
   Throw new Exception("Failed to finish ZipArchive."); 
  }
 
 }catch(Exception $e){
  # Vang alle Exceptions en print een error. maak hier wat beters van natuurlijk.
  printf("\n<pre>\n Failed to add file to zipArchive.\n Error: %s\n</pre>\n", $e->getMessage());
 }

 # vernietig het zip object of het nou bestaat of niet.
 $zip = NULL;

 # en sluit de session, pas hierna kan een volgende request/ajax call beginnen.
 session_write_close();


Probeer het zo nog eens. Ik heb deze code niet getest maar zoiets zou gewoon best practice zijn. Gewoon wat basic error checking en met exceptions wordt fout afhandeling een stuk makkelijker. Let op dat je zip file wel al moet bestaan en anders moet je die eerst even aanmaken, desnoods met touch. Ook werkt de session lock niet als je dit script buiten een webserver draait dacht ik en zoals ik al zei kan ik die open flags ook compleet verkeerd hebben. Niet getest maar achja, ik had toch niks te doen. Veel plezier ermee.

Acties:
  • 0 Henk 'm!

  • Cascade
  • Registratie: Augustus 2006
  • Laatst online: 16-09 11:44
Wat een post, en dat om half vijf s'-nachts. _/-\o_

Wel een kanttekening / wat geneuzel / niet belangrijk gezeur >:) :
• je kan best session_start() 2 x achter elkaar doen, levert alleen een E_NOTICE op. En een session is geen garantie voor een lock volgens mij.
• controle op $_GET['bron'] is tricky op deze manier. De trim op de $_GET['bron'] levert een string op ookal is $_GET['bron'] niet ge-set (wat ook een E_NOTICE zou opleveren), maar het komt later weer goed. Eigenlijk zou je $_SERVER['REQUEST_METHOD'] == 'GET' -> isset -> is_string -> trim -> strlen moeten doen.

Waar is TS? Is het al gelukt?

Acties:
  • 0 Henk 'm!

  • Marientjuh
  • Registratie: Oktober 2004
  • Laatst online: 09-09 13:44

Marientjuh

Fullstack developer

Als je op windows werkt zou ik eens gaan kijken naar WinZIP :) Ik heb ook ontzettend lang gestoeid met deze extensie en bij mij faalde die bij een bepaalde bestandsgrootte. Dit terwijl ik eigenlijk onbeperkt nodig had om in te pakken.

De commandline van WinZIP heeft de uitkomst gegeven.

Respect begint waar eigen kunnen ophoudt! - Kinderkleding webshop van vrouwlief: coz-adore.nl


Acties:
  • 0 Henk 'm!

Verwijderd

Cascade schreef op donderdag 09 juli 2009 @ 09:30:
Wat een post, en dat om half vijf s'-nachts. _/-\o_

Wel een kanttekening / wat geneuzel / niet belangrijk gezeur >:) :
• je kan best session_start() 2 x achter elkaar doen, levert alleen een E_NOTICE op. En een session is geen garantie voor een lock volgens mij.
• controle op $_GET['bron'] is tricky op deze manier. De trim op de $_GET['bron'] levert een string op ookal is $_GET['bron'] niet ge-set (wat ook een E_NOTICE zou opleveren), maar het komt later weer goed. Eigenlijk zou je $_SERVER['REQUEST_METHOD'] == 'GET' -> isset -> is_string -> trim -> strlen moeten doen.

Waar is TS? Is het al gelukt?
Volgens de docs creeert session_start wel degelijk een lock maar inderdaad alleen binnen een webserver waarbij de request dezelfde sessie-id gebruiken denk ik. Ik weet echter niet of dat ook opgaat voor custom-sessie handlers al denk ik wel aangezien ik denk dat er intern een lijstje met sessie-ids is dus de lock is voordat de sessie handler wordt aangeroepen, ook de build-in handler.

En als je het inderdaad helemaal volgens het boekje wil doen wordt het zoiets:
PHP:
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
function GetHTTPString($key, $max, $min)
{
 if((isset($_SERVER["REQUEST_METHOD"]) !== true) OR ($_SERVER["REQUEST_METHOD"] !== "GET")){
  throw new Exception("HTTP request modus is niet HTTP GET.");
 }
 if((is_string($key) !== true) OR (strlen($key) < 1)){
  throw new Exception("Naam van waarde om uit de HTTP GET request te halen is niet in string format.");
 }
 if((is_int($max) !== true) OR ($max < 0)){
  throw new Exception("Maxium lengte van waarde is geen geldige integer waarde.");
 }
 if((is_int($min) !== true) OR ($min < 0)){
  throw new Exception("Minium lengte is geen geldige integer waarde.");
 }

 if(isset($_GET[$key]) !== true){
  throw new Exception("Waarde ontbreekt in HTTP GET request.");
 }

 if((is_string($_GET[$key]) !== true) OR (strlen($_GET[$key]) < 1)){
  throw new Exception("Waarde in HTTP GET request is niet in geldig string formaat.");
 }

 $waarde = trim($_GET[$key]);
 if((is_string($waarde) !== true) OR (strlen($waarde) < $min) OR (strlen($waarde) > $max)){
  throw new Exception("Waarde is niet in geldig string format.");
 }

 return $waarde;
}


Je kunt dit dan gewoon aanroepen als: $bron = GetHTTPString("bron", 255, 1); zeer handig!

@Marientjuh
Ik heb zelf nooit met ZipArchive gewerkt maar wel met de zip functies en ik vondt ze inderdaad erg buggy. Dat was een lange tijd terug toen ZipArchive nog niet eens bestond maar ik krijg het idee dat ZipArchive gewoon een OO-wrapper is om dezelfde zip functies. Zelf zou ik inderdaad eerder exec() gebruiken of zelf een kwalitatief betere OO classe schrijven en deze extensie mijden. Ik zou zip zowieso mijden omdat het in mijn optiek toch een windows-only formaat is en eerder naar andere cross-plaftorm formaten zoals tar kijken.
Pagina: 1