Guardar una respuesta HTTP a un fichero en Laravel

Usando Laravel, podemos configurar la descarga de un fichero para que se vaya guardando directamente en una carpeta en local a través del método `sink`.

Guardar una respuesta HTTP a un fichero en Laravel
Photo by Sanibell BV / Unsplash

Estos días he estado trabajando en una aplicación muy data-intensive, con muchos muchos GB de datos que tienen que ser descargados e importados a la base de datos.

Cada uno de estos ficheros puede pesar hasta 2GB, por lo que si ejecutamos el siguiente código:

$csv = Http::timeout(0)
	->get($urlFichero)
	->body();

En este código descargamos un fichero CSV. Además, como esperamos que la descarga se tome su tiempo (2GB es bastante!) tenemos que ponerle un timeout alto o de cero (sin límite de tiempo). Sin embargo, una vez se complete la descarga, veremos un súper error de PHP de que no tiene memoria suficiente.

Para solucionar esto, podemos configurar la descarga para que se vaya guardando directamente en una carpeta en local, tal y como hacen los navegadores al descargar un fichero. Podemos streamear una descarga directamente a un fichero a través del método sink():

$disk = Storage::disk('local');
$fileName = 'data.csv';
Http::timeout(0)
	->sink($disk->path($fileName))
	->get($urlFichero);

Tras ejecutar este código, terminarás con un fichero data.csv en tu carpeta storage/app/data.csv.

En mi caso, tras descargar el fichero, lo fui leyendo línea a línea para ejecutar las acciones que necesitaba con cada elemento del CSV, aunque eso lo explicaré en otro post.