Export download prompt

https://filamentphp.com/docs/3.x/actions/prebuilt-actions/export Unless im blind, is there a way to click export, then prompt the ability for the user to download and save to their device, rather than saving in storage? As im assuming this is gonna require a separate link or button to doiwnload the exported file?...
18 Replies
lukevi
lukevi8mo ago
I would prefer this too - my exports are not large enough to justify the backgrounding & db-notification requirements
toeknee
toeknee8mo ago
No, the way the system is designed is for batch exporting not direct. It has performance in mind for bulk exporting. You could see if Dan would accept a PR for a new method: download() which runs the functions opposed to jobbing it and then downloads it directly. i.e. ->download(queue) or ->download(direct)
nowak
nowak8mo ago
I would love to see this too!
Jamie Cee
Jamie CeeOP7mo ago
Apologies for the delayed reply. Defo something useful, but would have to be something I'd have to gain time for.
toeknee
toeknee7mo ago
Dan is looking to add a direct() method possibility.
Jamie Cee
Jamie CeeOP7mo ago
direct? As in directing what to do with the export?
toeknee
toeknee7mo ago
A direct download type.
Jamie Cee
Jamie CeeOP7mo ago
Ah, yeah would be great. Just the naming of "direct" threw me off a little 🤣 But yeah, from a client using the cms POV, would be great to allow them to obtain the export
nowak
nowak7mo ago
Is there a PR or issue for this that we can follow?
toeknee
toeknee7mo ago
Not at present, I'll look to create one
nowak
nowak7mo ago
Thank you!
Jamie Cee
Jamie CeeOP7mo ago
@toeknee Were you in the progress of doing a PR for the ability to download an export?
toeknee
toeknee7mo ago
I didn't get round to it, so please feel free!
Jamie Cee
Jamie CeeOP7mo ago
Cool, Ill take a look in my spare time, Just randomly sprung to mind while at work
Mustafa_Dev
Mustafa_Dev6mo ago
I was looking for this feature yesterday. So I think it's good to have.
Jamie Cee
Jamie CeeOP6mo ago
I totally forgot to have a look into it ngl. Ill have to try find some time
ericmp
ericmp6mo ago
agree ^^
Jamie Cee
Jamie CeeOP6mo ago
So Im almost certain there has to be an easier way, but for now, I made a custom action, and implemented the Export functionality from ExportCsv class.
class ExportUsersAction extends Action
{
use CanExportRecords;
}
class ExportUsersAction extends Action
{
use CanExportRecords;
}
Inside the class above, I have this function:
/* Create the csv to download */
public function downloadCsv(Exporter $exporter, string $query, Collection $records, array $columnMap)
{
$exceptions = [];

$processedRows = 0;
$successfulRows = 0;

$csv = \League\Csv\Writer::createFromFileObject(new SplTempFileObject());
$csv->setDelimiter(',');

$query = EloquentSerializeFacade::unserialize($query);

foreach ($exporter->getCachedColumns() as $column) {
$column->applyRelationshipAggregates($query);
$column->applyEagerLoading($query);
}

$csv->insertOne(array_values($columnMap));

foreach ($records as $record) {
try {
$csv->insertOne(($exporter)($record));

$successfulRows++;
} catch (\Throwable $exception) {
$exceptions[$exception::class] = $exception;
}

$processedRows++;
}

// Return the CSV content as a downloadable response
// Create a StreamedResponse to output the CSV content
$response = new \Symfony\Component\HttpFoundation\StreamedResponse(function () use ($csv) {
echo $csv->toString();
});

// Set the headers to force download
$response->headers->set('Content-Type', 'text/csv');
$response->headers->set('Content-Disposition', 'attachment; filename="data.csv"');

if ($response) {
/* Do we prompt the user to download */
Notification::make()
->title("Exporting CSV file")
->body("Exporting content to CSV file")
->success()
->duration(5000)
->send();
}

return $response;
}
/* Create the csv to download */
public function downloadCsv(Exporter $exporter, string $query, Collection $records, array $columnMap)
{
$exceptions = [];

$processedRows = 0;
$successfulRows = 0;

$csv = \League\Csv\Writer::createFromFileObject(new SplTempFileObject());
$csv->setDelimiter(',');

$query = EloquentSerializeFacade::unserialize($query);

foreach ($exporter->getCachedColumns() as $column) {
$column->applyRelationshipAggregates($query);
$column->applyEagerLoading($query);
}

$csv->insertOne(array_values($columnMap));

foreach ($records as $record) {
try {
$csv->insertOne(($exporter)($record));

$successfulRows++;
} catch (\Throwable $exception) {
$exceptions[$exception::class] = $exception;
}

$processedRows++;
}

// Return the CSV content as a downloadable response
// Create a StreamedResponse to output the CSV content
$response = new \Symfony\Component\HttpFoundation\StreamedResponse(function () use ($csv) {
echo $csv->toString();
});

// Set the headers to force download
$response->headers->set('Content-Type', 'text/csv');
$response->headers->set('Content-Disposition', 'attachment; filename="data.csv"');

if ($response) {
/* Do we prompt the user to download */
Notification::make()
->title("Exporting CSV file")
->body("Exporting content to CSV file")
->success()
->duration(5000)
->send();
}

return $response;
}
And inside the setUp function, then inside $this->action() function, I call
return $action->downloadCsv($exporter, $serializedQuery, $records, $columnMap);
return $action->downloadCsv($exporter, $serializedQuery, $records, $columnMap);
Very unique to my case, so not ideal to use as a PR It does still populate the exports table, but doesn't run through the queue etc But I got lost navigating around things and finding where the best part to break it out would be, So if anyone does go and make a PR for the download feature, lemme know 😄
Want results from more Discord servers?
Add your server