¿Es correcto crear un archivo de esta manera?

X

xcodex

Hola!, hace unos días publiqué que me encontraba creando un archivo CVS, la diea siempre fué que descargue uno, y que se copie en el servidor, pero esto último no lo puedo lograr:
Este es el código:

PHP:
<?php
require "../include/bd-connect.php";
$pdo = bd_connect();

//Header
header("Content-Type:text/csv; charset=utf-8");
header("Content-Disposition: attachment; filename=report.csv");

//Salida de archivo
$exit = fopen("php://output", "w");
$exit2 = fopen("report.csv", "w");

//Encabezados:
fputcsv($exit, array('id', 'Title'));
fputcsv($exit2, array('id', 'Title'));

//Consulta para crear reporte:
$sql_libros = $pdo->prepare("SELECT id,title FROM books WHERE active = 1 ORDER BY id ASC");
$sql_libros->execute();
$resultado_libros = $sql_libros->fetchAll();

foreach ($resultado_libros as $row) {
    fputcsv($exit, array($row["id"], $row["title"]));
    fputcsv($exit2, array($row["id"], $row["title"]));
}
?>

Los errores que me aparecen son, uno de permisos al hacer:
PHP:
$exit2 = fopen("report.csv", "w");
Y luego cuando hace el encabezado:
PHP:
fputcsv($exit2, array('id', 'Title'));
y en el foreach:
PHP:
fputcsv($exit2, array($row["id"], $row["title"]));
me dice que espera un valor booleando.
Y bueno, no se que hacer. ¿Alguna sugerencia?.
 

Stron

Eta
Diseñador
Verificación en dos pasos activada
Verificado por Whatsapp
Desde
11 Oct 2015
Mensajes
1.271
X

xcodex

PHP:
<?php

//Encabezados:
fputcsv($exit, array('id', 'Title'));
fputcsv($exit2, array('id', 'Title'));

?>

Yo he probado un código similar en mi localhost y funciona bien, prueba quitando los encabezados, debería bastar con el foreach,
mira la documentación https://www.php.net/manual/es/function.fputcsv.php
Me parece rarísimo, además el problema es cuando hago ambo archivos en simultáneo, cuando hago cada uno por separado todo funciona correcto.
 

Stron

Eta
Diseñador
Verificación en dos pasos activada
Verificado por Whatsapp
Desde
11 Oct 2015
Mensajes
1.271
Me parece rarísimo, además el problema es cuando hago ambo archivos en simultáneo, cuando hago cada uno por separado todo funciona correcto.

Mira, entonces solo llama a este:
PHP:
$exit2 = fopen("report.csv", "w");

el archivo se creará en donde le indiques, y ya después lo llamas, así evitas ejecutar los dos al mismo tiempo.
 

Mask7OfDragon

VIP
Zeta
Verificación en dos pasos activada
Verificado por Whatsapp
¡Ha verificado su Paypal!
Suscripción a IA
Desde
17 Mar 2017
Mensajes
1.993
es incorrecto

function csvstr(array $fields) : string
{
$f = fopen('php://memory', 'r+');
if (fputcsv($f, $fields) === false) {
return false;
}
rewind($f);
$csv_line = stream_get_contents($f);
return rtrim($csv_line);
}

puede usar esto como referencia.
 

osqar

No recomendado
Verificación en dos pasos desactivada
Verificado por Whatsapp
¡Ha verificado su Paypal!
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
10 Nov 2015
Mensajes
362
No lo cerras al archivo con fclose?, ademas si estas usando un solo nombre vas a tener problema de concurrencia si dos ejecutan a la vez el php, tendrias concatenarle el timestamp por ahi al nombre.
 

hasdpk

Delta
Programador
Verificación en dos pasos desactivada
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
30 Abr 2013
Mensajes
602
Me voy a tomar el lujo de darte un par de recomendaciones.
  1. NO incluyas un Header antes de tener el archivo listo para salir. Si se genera algún error, dicho error sí o sí se va a descargar como CSV, y eso, está mal.
  2. No considero que sea necesario especificar el nombre de las columnas en "//Encabezados:". Técnicamente tienes un `array` asociativo, así que podrías sacar las `keys` para obtener las columnas que tendrá el CSV. Imagina si el día de mañana necesitas añadir nueva columna ¿Cuántos pasos necesitarás para poder añadirla?
  3. No empezaría a abrir el archivo hasta que tenga la respuesta del SQL ¿Qué pasaría si el SQL falla o hay un bug? La conexión con los archivos se quedaría abierta.
  4. Como te han recomendado, yo crearía el archivo en el servidor con un hash que lo identifique inequívocamente, por ejemplo la fecha y la hora. Después ese archivo se lo enviaría al cliente.
 
X

xcodex

Me voy a tomar el lujo de darte un par de recomendaciones.
  1. NO incluyas un Header antes de tener el archivo listo para salir. Si se genera algún error, dicho error sí o sí se va a descargar como CSV, y eso, está mal.
  2. No considero que sea necesario especificar el nombre de las columnas en "//Encabezados:". Técnicamente tienes un `array` asociativo, así que podrías sacar las `keys` para obtener las columnas que tendrá el CSV. Imagina si el día de mañana necesitas añadir nueva columna ¿Cuántos pasos necesitarás para poder añadirla?
  3. No empezaría a abrir el archivo hasta que tenga la respuesta del SQL ¿Qué pasaría si el SQL falla o hay un bug? La conexión con los archivos se quedaría abierta.
  4. Como te han recomendado, yo crearía el archivo en el servidor con un hash que lo identifique inequívocamente, por ejemplo la fecha y la hora. Después ese archivo se lo enviaría al cliente.
Gracias por tu respuesta.
¿Podría consultarte como quedaría mas o menos en mi código?
 

Stron

Eta
Diseñador
Verificación en dos pasos activada
Verificado por Whatsapp
Desde
11 Oct 2015
Mensajes
1.271
Mira yo sugiero primero crear el fichero, y después compruebas que existe en tu servidor, y recién ahí forzar la descarga.

PHP:
<?php

require "../include/bd-connect.php";

$pdo = bd_connect();

//Salida de archivo

$exit2 = fopen("report.csv", "w");

//Consulta para crear reporte:

$sql_libros = $pdo->prepare("SELECT id,title FROM books WHERE active = 1 ORDER BY id ASC");

$sql_libros->execute();

$resultado_libros = $sql_libros->fetchAll();

foreach ($resultado_libros as $row) {

    fputcsv($exit2, array($row["id"], $row["title"]));

}

fclose($exit2);


// forzar la descarga del archivo.
$nombre_fichero = 'report.csv';

if (file_exists($nombre_fichero)) {

    header("Content-Type:text/csv; charset=utf-8");
    header("Content-Disposition: attachment; filename=".$nombre_fichero);
   
    readfile($nombre_fichero);
    exit;
} else {

    echo "El fichero $nombre_fichero no existe";

}

?>
 
X

xcodex

Mira yo sugiero primero crear el fichero, y después compruebas que existe en tu servidor, y recién ahí forzar la descarga.

PHP:
<?php

require "../include/bd-connect.php";

$pdo = bd_connect();

//Salida de archivo

$exit2 = fopen("report.csv", "w");

//Consulta para crear reporte:

$sql_libros = $pdo->prepare("SELECT id,title FROM books WHERE active = 1 ORDER BY id ASC");

$sql_libros->execute();

$resultado_libros = $sql_libros->fetchAll();

foreach ($resultado_libros as $row) {

    fputcsv($exit2, array($row["id"], $row["title"]));

}

fclose($exit2);


// forzar la descarga del archivo.
$nombre_fichero = 'report.csv';

if (file_exists($nombre_fichero)) {

    header("Content-Type:text/csv; charset=utf-8");
    header("Content-Disposition: attachment; filename=".$nombre_fichero);
  
    readfile($nombre_fichero);
    exit;
} else {

    echo "El fichero $nombre_fichero no existe";

}

?>
Wooow, muchas gracias :) :)
 

¡Regístrate y comienza a ganar!

Beneficios

  • Gana dinero por participar
  • Gana dinero por recomendarnos
  • Descubre ofertas de empleo diariamente
  • Negocios seguros
  • ¡Información premium y más!

Acceder

¿Ya tienes una cuenta? Accede aquí

Arriba