Zdravím,
Mám projekt na webhostingu, kde mi zbývá 20 MB do FTP kvóty a potřebuju zapisovat do textového souboru, který má rozbalený 26 MB a sbalený 2 MB (ve formátu .gz, který preferuju).
Prozatím nechci připlácet za místo.
Chtěl bych soubor zabalit bez překročení kvóty.
Zkoušel jsem:
---PHP kód:
$fp = fopen("compress.zlib://soubor.txt.gz");
fwrite($fp, "...");
fclose($fp);
---PHP kód:
$gz = gzopen("soubor.txt.gz", "wb");
gzwrite($fp, "...");
gzclose($fp);
---PHP kód:
$output = "<obsah souboru>";
unlink("soubor.txt.gz");
$output = gzencode($output, 9); // zkoušel jsem různé parametry komprese i FORCE_GZIP i FORCE_DEFLATE
file_put_contents("soubor.txt.gz", $output); // nebo zápis $output přes fopen() a fwrite();
Všechno selže - hodí chybu 500. Předpokládám, že oba způsoby se dočasně snaží vytvořit 26MB soubor, narazí na kvótu a skončí chybou. (Kdyžtak upozorněte, pokud je to chybný předpoklad.)
Zkoušel jsem velikost nesbaleného souboru omezit pod kvótu, pak ve všech případech vše dopadlo bez chyby.
Jestli víte, prosím, poraďte, jak soubor sbalit. Díky.
(hosting jede na PHP 7.3.26, ini(memory_limit)=128M, všechny běžné knihovny pro archivy povolené)
Zápis do.gz za běhu
Co se právě děje na Webtrhu?
- Softikon.eu poptává: Frontend engineer
- Yuriix poptává: Koupím CashBack portál - zaběhnutý nebo jen systém
- Jan654 poptává: Online docházka
chtělo by to vědět tu chybu, kterou to vyhodí. Nechceš si jí někam vypsat?
Zkoušel jsi ty tvoje příklady s malými soubory, jestli to také vyhodí chybu?
Podle mě ty kódy nevytváří dočasný rozbalený soubor a dělají to in-memory
Kdyby sis priplatil ta ten hosting, tak vlastně ne výsledku usetris víc, nez kdyz se s tom budes tyden mrdat
500 Internal Server Error - HTTP | MDNchtělo by to vědět tu chybu, kterou to vyhodí. Nechceš si jí někam vypsat?
Pokud před tím nezapíšu nic na výstup (tj. lze modifikovat HTTP hlavičky), pak se z výsledku nezobrazí nic a dostanu standardní hlášku 500 Internal Server Error (každý prohlížeč to interpretuje po svém). Pokud před tím něco na výstup zapíšu, tak v daném místě výstup HTML skončí. Nic mezi tím, ani pro error_reporting(E_ALL);
Zápis menšího souboru je bez chyb (jak jsem zmínil).Zkoušel jsi ty tvoje příklady s malými soubory, jestli to také vyhodí chybu?
Co znamená „in-memory“? A co ohledně toho mohu udělat?Podle mě ty kódy nevytváří dočasný rozbalený soubor a dělají to in-memory
Strašně pomohlo, dík.Kdyby sis priplatil ta ten hosting, tak vlastně ne výsledku usetris víc, nez kdyz se s tom budes tyden mrdat
Pokud dobře chápu, otevření gz souboru pro zápis a samotný zápis malých dat funguje.
Ta data do souboru zapisuješ jako jeden celek, nebo jsi zkoušel i zapisovat po částech?
gzopen, fopen a pod. by měly jen otevřít soubor a v paměti si udržují ukazatel na pozici v tom souboru (proto in-memory = neměl by se vytvářet tmp file na disku)
No, já myslel tu chybu v php, která způsobila ten 500 Internal Server Error, je jedno, že to každý prohlížeč zobrazí jinak, je důležité vědět, proč jí php způsobilo. Pokud nepoužíváš nějaký framework, který to ošetřuje nebo nemáš přístup k php logům, můžeš si nadefinovat vlastní error handler, viz https://www.php.net/manual/en/functi...or-handler.php
Tj. hoď úplně na začátek skriptu něco takovéhoto, odchytí to chyby a vypíše na výstup.
Pokud chceš potlačit násilně tu 500 hlavičku (aby ti prohlížeč vypsal text chyby a ne jeho chybovou hlášku), stačí dát na začátek skriptu prázdné echo, vypíšou se tím hlavičky, pro jistotu i vypínám output buffering.PHP kód:
<?php
set_error_handler(function($errno, $errstr, $errfile, $errline ){
$err = htmlspecialchars($errstr);
echo "Error $errno on line $errline in file $errfile";
echo "$err";
});
Kód na první pohled vypadá dobře, teď jsem to vyzkoušel a v php 7 bez problémů zapíšu 1 MB soubor na 1,1 MB velký disk.PHP kód:
<?php
ob_end_flush();
ob_implicit_flush();
echo "";
To bych také rád věděl. Žádná hláška se nevypisuje. Asi jsi automaticky předpokládal, že to tak musí být, ale není tomu tak. Díky za radu s error handlerem, ale nepomohla - ať s ním či bez něj dostanu buď vše bez chyb nebo 500 na úrovni serveru a nic mezi (jak jsem již psal). Ani, když echo v handleru změním na zápis do souboru, po spuštění se nevytvoří. Skoro jako by vykonávání skriptu utnulo něco o úroveň výš.No, já myslel tu chybu v php, která způsobila ten 500 Internal Server Error, ...
Btw, fwrite, gzwrite a file_put_contents při chybě nehází chybu, jen vrátí false. Zmínku o případu, kdy není dost místa, jsem na php.net nezahlédl. Po chvilce googlování jsem narazil akorát na hlášku "Disk quota exceeded (122) in /path/file at line #" viz, ale to může být specifické ke knihovně na dané stránce.
Ano.Pokud dobře chápu, otevření gz souboru pro zápis a samotný zápis malých dat funguje.
Všechny způsoby, které jsem uvedl na začátku tohoto threadu.Ta data do souboru zapisuješ jako jeden celek, nebo jsi zkoušel i zapisovat po částech?
používáš nějaký framework nebo redakční systém? Nějak se mi nezdá, že by chyba nešla odchytit a poslat na výstup. Ten error handler může někdo další přepsat.
Apache má php napojené přes (f)cgi, vyhazuje 500 pokud samotné php se ukončí (aka proces umře aniž by poslal chybu ven, to by byl nejspíš špatně natavený hosting a chyba v jejich systémovém logu).
Těžko říct bez dalších podrobností.
Ne - čisté PHP. Přemýšlím, že bych na to zkusil přidat Tracy, ale pochybuju, že by to pomohlo.používáš nějaký framework nebo redakční systém?
Avast Secure Browser. V normálním Chrome je stejná chyba, zobrazená jinak.jaký používáš prohlížeč? Tuhle stránku s chybou neznám, výchozí vypadá jinak, to máš vlastní?
Musis mrknout do error logu apache, uz leta se nedoporucuje an produkci mit vystupy php chyb primo do prohlizece, takze pokud mas hosting co to dodrzuje, tak se v prohlizeci nedozvis vic nez ze se neco nepovedlo...
prpadne muzes zkusit
zalezi jestli to hosting ma povolene, nektere ne...PHP kód:
ini_set('display_errors', 1);
zkus si to na jiném hostingu nebo u sebe. Případně sem hoď celý kód a výpis php ini. U všech tří variant tvého pseudokódu jsem byl schopný zapsat soubor na plný disk, pokud zapisuji více než se na disk vejde, php končí warningem a nikoliv fatal error.
Opravdu to s menším souborem zapíšeš bez chyby? Memory limit 128 MB je opravdu aplikovaný? Jakou velikost mají data, když jsou rozbalená, vejdou se do paměti a náhodou nekončí to na out of memory chybě kvůli vysoké efektivitě komprese?
Jakým způsobem se dostanou data do proměnné v php?
Jsou přijímána z POSTu, nebo jsou načítána ze vzdáleného zdroje, případně jak?
Pokud jsou přijímána z POSTu (resp $_FILES), tak to možná umře na tmp file, do kterého se ukládá vstup. K samotnému scriptu a ukládání gz pak vůbec nedojde.
$_FILES['userfile']['tmp_name']
"The temporary filename of the file in which the uploaded file was stored on the server."
Ten tmp file se možná (přišlo by mi to logické) bude počítat do diskové kvoty taky.