Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Out of memory przy otwieraniu pliku xlsx
Forum PHP.pl > Forum > Przedszkole
grzecho83
Witam, używam biblioteki SimpleXLSX.php do odczytu plików *.xlsx, przy próbie otwarcia pliku pojawia się błąd:

Fatal error: Out of memory (allocated 83886080) (tried to allocate 29970075 bytes) in /***/SimpleXLSX.php on line 535

Na domowym serwerze XAMP działa ok, problem jest po wgraniu strony na serwer zewnętrzny. W pomocy technicznej dowiedziałem się że mają limit pamięci dla php 128MB i nie można go zwiększyć.
Plik *.xlsx ma rozmiar na dysku 6,2MB, więc dlaczego rozmiar jest przekroczony? Kod PHP otwierający plik też nie jest jakoś mocno rozbudowany.
Pytanie, czy można jakoś zoptymalizować tą bibliotekę?
LInk do strony z biblioteką simplexlsx
viking
Chcesz żebyśmy patchowali zewnętrzną bibliotekę? Zgłoś błąd, pokaż swój kod. Pewnie autor będzie chciał też zobaczyć twój plik.
kreatiff
Wielkość pliku na dysku nie oznacza, że właśnie tyle RAMu zużyje aplikacja go otwierająca czy przetwarzająca. Jeśli go wczytuje całego do pamięci, to oznacza, że wielkość pliku w MB oznacza prędzej minimalne zużycie RAMu.
Albo gdzieś jest błąd w klasie powodujący wyciek pamięci dla tego pliku, albo to normalne, że działania na pliku pochłaniają właśnie takie ilości RAMu.

Możesz zmierzyć na localhost ile RAMu jest zaalokowane w szczytowym momencie. I jeśli >128 MB, to nic tutaj nie pomoże: https://www.php.net/manual/en/function.memo...-peak-usage.php

Masz możliwość przerobienia tego xlsx na csv? Jeśli tak, odejdzie masa problemów i to będzie najlepsze rozwiązanie.

A jeśli nie, to możesz też spróbować innej biblioteki, np.: https://github.com/PHPOffice/PhpSpreadsheet/
vokiel
Cytat(viking @ 1.05.2020, 09:52:02 ) *
Chcesz żebyśmy patchowali zewnętrzną bibliotekę? Zgłoś błąd, pokaż swój kod. Pewnie autor będzie chciał też zobaczyć twój plik.


Nie trzeba nic patchować, po prostu brakuje mu pamięci na wykonanie skryptu.


Cytat(grzecho83 @ 1.05.2020, 09:21:19 ) *
Witam, używam biblioteki SimpleXLSX.php do odczytu plików *.xlsx, przy próbie otwarcia pliku pojawia się błąd:

Fatal error: Out of memory (allocated 83886080) (tried to allocate 29970075 bytes) in /***/SimpleXLSX.php on line 535

Na domowym serwerze XAMP działa ok, problem jest po wgraniu strony na serwer zewnętrzny. W pomocy technicznej dowiedziałem się że mają limit pamięci dla php 128MB i nie można go zwiększyć.
Plik *.xlsx ma rozmiar na dysku 6,2MB, więc dlaczego rozmiar jest przekroczony? Kod PHP otwierający plik też nie jest jakoś mocno rozbudowany.
Pytanie, czy można jakoś zoptymalizować tą bibliotekę?
LInk do strony z biblioteką simplexlsx


128M to dość mało na przetwarzanie plików. Zorientuj się czy wykonując skrypt przez CLI nie możesz mieć większego limitu.

Jeśli nie, to pozostaje przejście na strumieniowe przetwarzanie danych, które jest mniej zasobożerne.
grzecho83
Plik csv byłby dużo lepszy, od takiego zaczynałem budowę systemu i na tym działało super, ale dane mam w pliku xlsx.

Powiem w skrócie na czym polega ten system. Mamy wykupione oprogramowanie do zarządzania zamówieniami, ten system co godzinę eksportuje plik xlsx z wszystkimi zamówieniami na dysk google.
Ja buduje system który pobiera ten plik z dysku google na serwer, otwiera go i szuka w nim nowych zamówień. Nowe zamówienia wrzuca do mazy danych. Na podstawie tych zamówień zleca produkcję podzespołów i zarządza całym procesem produkcji.
W pliku jest już 8611 wierszy, i przybywa czasem po kilkanaście dziennie. Wiięc zwiększenie limitu nie pomoże bo problem kiedyś wróci, jeśli przybędzie odpowiednio dużo zamówień. Ręczny export do csv też odpada bo to jest kilka razy dziennie. Idealne było by gdybym znalazł sposób na automatyczny export do csv po pobraniu pliku.

Sprawdzę też PhpSpreadsheet, który polecacie. Ale podejrzewam że też będzie miał pewne ograniczenia, pliki CSV były otwierane linijka po linijce, i nie miało wielkiego znaczenia ile tych wierszy jest. Dowiem się też czy system do zamówień może exportowć dodatkowo dane w formie csv.
trueblue
Plik xlsx do de facto plik zip. Zmień rozszerzenie i zobacz jak wygląda archiwum w środku. Może łatwiej by było wydobyć dane o konkretnym arkuszu właśnie z tego archiwum (są to dane w formacie XML - /xl/worksheets/) i je przetwarzać. Oczywiście pod warunkiem, że nie ma tam formuł.
grzecho83
Cytat(trueblue @ 1.05.2020, 16:12:21 ) *
Plik xlsx do de facto plik zip. Zmień rozszerzenie i zobacz jak wygląda archiwum w środku. Może łatwiej by było wydobyć dane o konkretnym arkuszu właśnie z tego archiwum (są to dane w formacie XML - /xl/worksheets/) i je przetwarzać. Oczywiście pod warunkiem, że nie ma tam formuł.

zmieniłem rozszerzenie, znalazłem pliki tam gdzie wskazałeś, było tyle plików ile zakładek w dokumencie, ale nie wiem jak wyciągnąć konkretne dane. Plik xml otwierałem w notepad++, w wyszukiwarce wpisywałem wartości przypadkowych komórek i nic nie znalazło, w pliku są same liczby i przypadkowo wyglądające znaki, poza znacznikami xml. w pliku na pewno nie ma formuł, są suche dane.
Druga sprawa to nie wiem czy z poziomu php da się rozpakować plik zip.
trueblue
Archiwum ZIP można tworzyć i obsługiwać w PHP.


1 a
2 b
3 c

Przykładowy fragment XML dla powyższych danych:

  1. <sheetData>
  2. <row r="1" customFormat="false" ht="12.8" hidden="false" customHeight="false" outlineLevel="0" collapsed="false">
  3. <c r="A1" s="0" t="n">
  4. <v>1</v>
  5. </c>
  6. <c r="B1" s="0" t="s">
  7. <v>0</v>
  8. </c>
  9. </row>
  10. <row r="2" customFormat="false" ht="12.8" hidden="false" customHeight="false" outlineLevel="0" collapsed="false">
  11. <c r="A2" s="0" t="n">
  12. <v>2</v>
  13. </c>
  14. <c r="B2" s="0" t="s">
  15. <v>1</v>
  16. </c>
  17. </row>
  18. <row r="3" customFormat="false" ht="12.8" hidden="false" customHeight="false" outlineLevel="0" collapsed="false">
  19. <c r="A3" s="0" t="n">
  20. <v>3</v>
  21. </c>
  22. <c r="B3" s="0" t="s">
  23. <v>2</v>
  24. </c>
  25. </row>
  26. </sheetData>


Stringi powyżej zapisane są jako indeksy do stringów w: xl\sharedStrings.xml
grzecho83
Dzięki za wytłumaczenie struktury pliku. Niestety u mnie wszystkie komórki w arkuszu zawierają stringi. mój algorytm przeszukuje kolejno wiersze sprawdzając datę dodania czy jest świeża. Gdyby chociaż data była w formie liczbowej, niestety to też string. Kolumna Opis zamówienia ma czasem ponad 1000 znaków. I może dlatego przekraczam zakres pamięci, skoro skrypt musi całość załadować do pamięci i jeszcze w międzyczasie przeszukiwać kolejny plik w poszukiwaniu stringów.
Chyba zostawię odczyt bezpośrednio z pliku xlsx. Po weekendzie zapytam dostawcę systemu z zamówieniami o możliwość eksportu do pliku CSV, a do tego czasu spróbuję znaleźć może sposób na szybką konwersję do CSV.
Tak na marginesie, mój plik *.xlsx po zmianie nazwy na *.zip i rozpakowaniu zajmuje już 40MB, i z każdym nowym zamówieniem będzie większy.
vokiel
A czy to oprogramowanie nie może eksportować w innym formacie?
Druga kwestia, czy nie mogłoby eksportować ograniczonej listy zamówień, a nie wszystkie od początku? Po co masz przetwarzać wszystkie jak masz np tylko 10 nowych.
trueblue
Cytat(grzecho83 @ 1.05.2020, 20:16:00 ) *
Dzięki za wytłumaczenie struktury pliku. Niestety u mnie wszystkie komórki w arkuszu zawierają stringi. mój algorytm przeszukuje kolejno wiersze sprawdzając datę dodania czy jest świeża. Gdyby chociaż data była w formie liczbowej, niestety to też string. Kolumna Opis zamówienia ma czasem ponad 1000 znaków.

Czyli tak naprawdę musiałbyś pobrać indeks i znajdywać w sharedStrings.xml odpowiadający mu string/datę i wtedy decydować o "zbudowaniu" reszty wiersza. Tyle, że u Ciebie, zresztą wspominasz o opisach, sam sharedStrings.xml stanowi problem.
grzecho83
Plik zawiera wszystkie zamówienia bo jest eksportowany w innym celu, do innego systemu który jest zbudowany na arkuszach google i potrzebuję wszystkich danych. Ja chciałem wykorzystać gotowe rozwiązanie do swojego systemu. Eksportowane są 4 pliki, ja potrzebuję jedną zakładkę jednego z nich. Widzę że korzystanie z gotowego rozwiązania będzie zbyt kłopotliwe. Dowiem się w poniedziałek, ale myślę że eksport do pliku csv nie będzie problemem. Może nawet da się exportować ostatnie zamówienia. Chociaż przeglądanie pliku z całości trwało kilka sekund, więc jeśli się nie da to nie będzie wielkim problemem.
javafxdev
Dziwne podejście biznesowe do tego masz.
Zakładając ze hosting serwera vps z 2GB ramu kosztuje ok 200 PLN na rok (pewnie znajdziesz coś tańszego - ale zakładając takie coś) i tam możesz zmienić limit dowolnie jak chcesz.
Biorąc pod uwagę ze przerobienie skryptu zajmie Ci 1 dzień - czyli 8h - to daje 25 PLN za godzine.
1) To jeżeli zarabiasz więcej to nie opłaca się w ogóle za to zabierać tylko kupić hosting podbić parametry i robić inne funkcjonalności.
2) Jeżeli zarabiasz mniej to przerobienie tego na jakieś pliki zip wyciąganie ze środka itp. zaciemni skrypt i późniejsza modyfikacja będzie dużo trudniejsza i bardziej kosztowna i pewnie też nie zrobisz tego w jeden dzień. - więc tutaj też patrz punkt 1.
gino
hmmm, przecież arkusze google mają możliwość i narzędzia i to dosyć dobre do pobierania danych bezpośrednio ze stron www, wystarczy, że będą to dane tabelaryczne a arkusze google same dokonają analizy tego co jest do pobrania. Nie traktował bym tych arkuszy jako zamiennika excel-a. Taka myśł mi się nasuwa.

gino
grzecho83
Cytat
1) To jeżeli zarabiasz więcej to nie opłaca się w ogóle za to zabierać tylko kupić hosting podbić parametry i robić inne funkcjonalności.
2) Jeżeli zarabiasz mniej to przerobienie tego na jakieś pliki zip wyciąganie ze środka itp. zaciemni skrypt i późniejsza modyfikacja będzie dużo trudniejsza i bardziej kosztowna i pewnie też nie zrobisz tego w jeden dzień. - więc tutaj też patrz punkt 1.

Ani jedna ani druga opcja nie ma sensu jeśli mogę mieć do dyspozycji plik CSV, a to będę wiedział w poniedziałek. Wtedy wyciągnę z archiwum kod który już mam napisany ( na początku pisałem pod CSV, bo myślałem że takie będę miał dane wyjściowe, małe nieporozumienie.)

Cytat
przecież arkusze google mają możliwość i narzędzia i to dosyć dobre do pobierania danych bezpośrednio ze stron www

to nie są arkusze google tylko pliki xlsx umieszczone na dysku google.

Pamiętajcie że temat nieprzypadkowo jest w dziale przedszkole, nie piszcie ze zdziwieniem że nie wiem o oczywistych rozwiązaniach. Dzięki wielkie że uświadomiliście mi problemy związane z odczytem plików XLSX, myślałem że to mniej skomplikowane.
gino
Ok tylko Ty wspomniałeś że dane idą do systemu zbudowanego z arkuszy google-a, może tam należałoby szukać rozwiązania. Poza tym za rok, dwa ten plik spuchnie tak, że prawie żaden host nie będzie go w stanie obsłużyć.

gino
grzecho83
Do konwertowania plików XLSX do arkuszy google używane jest narzędzie SheetGo, pliki są aktualizowane raz dziennie o północy, to dla mnie za rzadko, pliki XLSX na dysku mam aktualne co godzinę.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.