Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Generowanie CSV i zapis do pliku - nie działa ;(
Forum PHP.pl > Forum > Przedszkole
phpamator
Hej,
to znowu ja Wasz niepoprawny/niereformowalny phpamator (jak widać)

Napotkałem problem z którym nie potrafię sobie poradzić, może ktoś z was mógłby mnie oświecić.
Otóż pisząc mój kod który teoretycznie powinien działać (kod poniżej)

  1. // sprawdzam czy są jakieś elementy zaznaczone, jeśli tak to lista "id" jest wysyłana do php - i to działa, dane są wysyłane
  2. // lub jeśli nie zaznaczone wysyła tylko sygnał i wszystkie dane są wyrzucane do csv ale ...
  3. $('#csvexport').on('click',function(){
  4. var selected = new Array();
  5. $('table input[type="checkbox"]:checked').each(function() {
  6. selected.push($(this).attr('id'));
  7. });
  8. if (selected.length > 0)
  9. {
  10. selected = selected ;
  11. }
  12. else
  13. {
  14. selected = null ;
  15. }
  16. event.preventDefault();
  17. $.ajax({
  18. type: "POST",
  19. url: "functions.php",
  20. data: {
  21. 'action': 'csvexport',
  22. 'userId': 1,
  23. 'selected': selected
  24. },
  25. // dataType: "json",
  26. // encode: true,
  27. }).success( function ( response ) {
  28. if( response == 1 )
  29. {
  30. alert ( 'CSV Exported' ) ;
  31. // alert ( 'Export failed!' ) ;
  32. spinner() ;
  33. }
  34. spinner() ;
  35. });
  36. });

  1. // .... ale mimo to nie dostaję nic spowrotem. spodziewam się że wyskoczy okienko i poprosi o wskazanie miejsca gdzie zapisać
  2. // mój CSV
  3. if (isset($_POST['action']) && $_POST['action'] == 'csvexport')
  4. {
  5. if ( $_POST['selected'] == false )
  6. {
  7. $data = null ;
  8. }
  9. else
  10. {
  11. $data = $_POST['selected'] ;
  12. }
  13. $userId = $_POST[ 'userId' ] ;
  14. exportCsv( $userId, $data ) ; funkcja powinna zwrócić dane/plik
  15. }
  16.  
  17. // pobieram dane do wygenerowania CSV
  18. function getCsvData( $data )
  19. {
  20. $link = getConfig() ;
  21. if ( !empty ( $data ) )
  22. {
  23. $clientData = $link->prepare("SELECT * FROM `mydb`.`mytable` WHERE `id` IN (".implode(',',$data).") ") ;
  24. }
  25. else
  26. {
  27. $clientData = $link->prepare("SELECT * FROM `mydb`.`mytable` ") ;
  28. }
  29. $clientData->execute() ;
  30. $result = $clientData->get_result() ;
  31. $assoc = $result->fetch_All(MYSQLI_ASSOC) ;
  32. return $assoc ;
  33. }
  34.  
  35. // tworzę plik CSV
  36. function exportCsv ( $userId, $data )
  37. {
  38. $clients = getCsvData($data) ;
  39. $output = fopen ( 'php://output', 'wb' ) ;
  40. fputcsv( $output, array_keys( $clients[0] ) ) ;
  41. foreach ( $clients as $client )
  42. {
  43. fputcsv( $output, $client ) ;
  44. }
  45. fclose( $output ) ;
  46. header ( 'Content-Type: text/csv; charset=utf-8' ) ;
  47. header ( 'Content-Disposition: attachment; filename=clients_report.csv' ) ;
  48. header ( 'Expires: 0' ) ;
  49. header ( 'Cache-Control: no-cache' ) ;
  50. header ( 'Content-Length: '. ob_get_length() ) ;
  51. }
  52.  
  53.  


wrzuciłem to do osobnego pliku i działa bez problemu

Co źle zrobiłem ?
nospor
Czy ja dobrze rozumiem ze slesz AJAX do pliku ktory wypluwa ci CSV z odpowiednimi headers i dziwisz sie ze sie nie schce sciagnac? No normalne. Poprostu przekieruj uztkownika do tego pliku a nie slesz tam AJAX.
Jak przekierowac? Normalnie,
document.location.href="adres do pliku"
phpamator
Teraz to ja nie rozumiem tongue.gif
żeby rozjaśnić:

mam tabele gdzie wybieram które dane chcę mieć w CSV
więc zaznaczam i wysyłam ajaxem
dwie funkcje użyte w tym przykładzie pobieraj i generuj plik i zapisuj do bufora
i tu spodziewałem się mojego pliku poprzedzonego pytaniem "Gdzie chcesz zapisać wygenerowany plik"

Jak ty "nospor" byś to zrobił ?

nospor
ok, nie dolukalem ze przesylasz parametry jeszcze
Tylko ze parametry nadal mozesz przeslac do pliku czyli nadal jak pisalem wczesniej


document.location.href="http://url_do_sciagniecia_pliku?tutaj_parametry"


Jesli jednak nadal sie upierasz przy ajax, to url na ktory idzie ajax ma nie zwracac pliku z naglowkami, tylko sama zawartosc pliku, ajax ja pobierzez i potem w js przygotowujesz zwrotke do pobrania pliku dla usera. W necie masz masze przykladow jak zrobic download w js
Salvation
Ja bym zrobił to inaczej. Plik wygenerował i zapisał po stronie PHP. Zwrócił na front jedynie zahashowaną nazwę pliku i front zrobiłby przekierowanie na ten właśnie plik do pobrania.
phpamator
Cytat(Salvation @ 13.10.2022, 17:22:08 ) *
Ja bym zrobił to inaczej. Plik wygenerował i zapisał po stronie PHP. Zwrócił na front jedynie zahashowaną nazwę pliku i front zrobiłby przekierowanie na ten właśnie plik do pobrania.


Mógł byś podeprzeć to jakimś przykładem ?
nospor
@Salvation skoro i tak musisz w twoim przypadku i tak we frontend przekierowac do pliku do sciagniecia, to czemu nie lepiej przekierowac do pliku ktory generuje co ma generowac? Wydaje sie to byc zbedna dodatkowa funkcjonalnoscia
Salvation
Kod masz już prawie gotowy. Wystarczy zmienić funkcję `exportCsv` na taką by zapisywała plik - na przykład z użyciem natywnych funkcji: https://www.php.net/manual/en/function.fputcsv.php lub z użyciem jakiejś bliblioteki. Jak Ci wygodniej.

Zamiast statycznej nazwy pliku: file.csv generuj ją sobie np. w ten sposób:
  1. $filenameHash = md5(sprintf('csvexport_%s_%s', $userId, time()));
  2. $filename = sprintf('%s.csv', $filenameHash);

I zwracaj albo sam hash ($filenameHash), albo nazwę z rozszerzeniem: $filename.

I w tym ifie co masz, to ostatnie dwie linijki zamieniasz na to:
  1. echo exportCsv($userId, $data);

Dodaj jeszcze tylko typowanie argumentów i typ zwrotek funkcji i będzie dobrze.

Cytat(nospor @ 14.10.2022, 10:06:41 ) *
@Salvation skoro i tak musisz w twoim przypadku i tak we frontend przekierowac do pliku do sciagniecia, to czemu nie lepiej przekierowac do pliku ktory generuje co ma generowac? Wydaje sie to byc zbedna dodatkowa funkcjonalnoscia

Tak, w sumie to masz rację z tym. Tylko nie wiem czy użycie przekierowania "jawnego" (bezpośredniego) nie zaburzy założeń biznesowych. Może jest jakiś powód do tego, że to leci po AJAX-ie.
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-2024 Invision Power Services, Inc.