logo
16.01.2021 02:17
1
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($output9); // 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é)

Co se právě děje na Webtrhu?

16.01.2021 09:34
2
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
16.01.2021 11:40
3
Kdyby sis priplatil ta ten hosting, tak vlastně ne výsledku usetris víc, nez kdyz se s tom budes tyden mrdat
17.01.2021 00:12
4
Původně odeslal TomášX
chtělo by to vědět tu chybu, kterou to vyhodí. Nechceš si jí někam vypsat?
500 Internal Server Error - HTTP | MDN

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);

Původně odeslal TomášX
Zkoušel jsi ty tvoje příklady s malými soubory, jestli to také vyhodí chybu?
Zápis menšího souboru je bez chyb (jak jsem zmínil).

Původně odeslal TomášX
Podle mě ty kódy nevytváří dočasný rozbalený soubor a dělají to in-memory
Co znamená „in-memory“? A co ohledně toho mohu udělat?

Původně odeslal jarocelebrate
Kdyby sis priplatil ta ten hosting, tak vlastně ne výsledku usetris víc, nez kdyz se s tom budes tyden mrdat
Strašně pomohlo, dík.
17.01.2021 01:29
5
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)
17.01.2021 01:39
6
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.
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";
});
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
ob_end_flush
();
ob_implicit_flush();
echo 
"";
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.
18.01.2021 01:21
7
Původně odeslal TomášX
No, já myslel tu chybu v php, která způsobila ten 500 Internal Server Error, ...
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ýš.


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.

Původně odeslal skorozacatecnik
Pokud dobře chápu, otevření gz souboru pro zápis a samotný zápis malých dat funguje.
Ano.
Původně odeslal skorozacatecnik
Ta data do souboru zapisuješ jako jeden celek, nebo jsi zkoušel i zapisovat po částech?
Všechny způsoby, které jsem uvedl na začátku tohoto threadu.
18.01.2021 02:24
8
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í.
18.01.2021 02:27
9
jaký používáš prohlížeč? Tuhle stránku s chybou neznám, výchozí vypadá jinak, to máš vlastní?
18.01.2021 14:41
10
Původně odeslal TomášX
používáš nějaký framework nebo redakční systém?
Ne - čisté PHP. Přemýšlím, že bych na to zkusil přidat Tracy, ale pochybuju, že by to pomohlo.
Původně odeslal TomášX
jaký používáš prohlížeč? Tuhle stránku s chybou neznám, výchozí vypadá jinak, to máš vlastní?
Avast Secure Browser. V normálním Chrome je stejná chyba, zobrazená jinak.
18.01.2021 14:56
11
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
PHP kód:
ini_set('display_errors'1); 
zalezi jestli to hosting ma povolene, nektere ne...
18.01.2021 15:50
12
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?
18.01.2021 17:29
13
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.
20.01.2021 01:28
14
Původně odeslal Aleš Jiříček
PHP kód:
ini_set('display_errors'1); 
Díky moc, toto pomohlo.
Když to shrnu, vypsalo mi to hlášku, která sice souvisela s překročením místa v paměti -v procesu generování souboru-, ale ne s pakováním do .gz.
Po opravení vše funguje.
Díky všem za spolupráci.