Found a handful of questions on here about this with no answer, so hopefully, someone can point me in the right direction...
I'm trying to create and save a csv file to storage, then update the DB in Laravel. I can create the file successfully, and I can update the DB successfully... but I'm stuck on putting them both together. In my controller, I have this for creating the file (taken from here):
public function updatePaymentConfirm(Request $request) {
$users = User::all();
$fileName = 'test.csv';
$headers = array(
"Content-type" => "text/csv",
"Content-Disposition" => "attachment; filename=$fileName",
"Pragma" => "no-cache",
"Cache-Control" => "must-revalidate, post-check=0, pre-check=0",
"Expires" => "0"
);
$columns = array('First Name', 'Email');
$callback = function() use($users, $columns) {
$file = fopen('php://output', 'w');
fputcsv($file, $columns);
foreach ($users as $user) {
$row['First Name'] = $user->first_name;
$row['Email'] = $user->email;
fputcsv($file, array($row['First Name'], $row['Email']));
}
fclose($file);
};
// return response()->stream($callback, 200, $headers);
}
When the function completes, the last line (that's commented out) prompts the user to download the newly created file (which is not the functionality I'm looking for). I tried adding this to my controller in its place for saving to storage and also updating the database:
$fileModel = new UserDocument;
if($callback) {
$filePath = $callback->storeAs('uploads', $fileName, 'public');
$fileModel->name = $fileName;
$fileModel->file_path = '/storage/' . $filePath;
$fileModel->save();
return back()
->with('success','File has been uploaded.')
->with('file', $fileName);
}
It saves a row to the db, albeit incorrectly, but it doesn't save the file to storage. I've reworked the $filePath line a million times, but I keep getting this error Call to a member function storeAs() on resource or something similar. I'm relatively new to working with Laravel, so I'm not sure what I should be looking for. Thoughts?
Removed everything and started over... got it! And for anyone else running into the same issue: just calling for a file that doesn't exist creates the file (unless the file exists - then it updates it), so you don't have to create a temp file or use $file = fopen('php://output', 'w'); to create the file. It'll automatically "save" the newly generated file in the file path you specified when you fclose() out of the file.
The only thing I'll note is that the file path has to exist (the file doesn't, but the file path does). In my instance, the file path already exists, but if yours doesn't or if you're not sure if it does, check to see if it exists, and then make the directory.
public function updatePaymentConfirm(Request $request) {
$user = Auth::user();
$path = storage_path('app/public/docs/user_docs/'.$user->id);
$fileName = $user->ein.'.csv';
$file = fopen($path.$fileName, 'w');
$columns = array('First Name', 'Email Address');
fputcsv($file, $columns);
$data = [
'First Name' => $user->first_name,
'Email Address' => $user->email,
];
fputcsv($file, $data);
fclose($file);
$symlink = 'public/docs/user_docs/'.$user->id.'/';
$fileModel = new UserDocument;
$fileModel->name = 'csv';
$fileModel->file_path = $symlink.$fileName;
$fileModel->save();
return redirect()->route('completed');
}
** UPDATE **
Everything worked perfectly locally, and when I pushed this to production, I received this error 🙄:
fopen(https://..../12-3456789.csv): failed to open stream: HTTP wrapper does not support writeable connections.
I'm saving to an s3 bucket, and I had to rework the entire process. You can't create and/or write to a file in the directory. I had to create a temp file first. Here's where I landed:
$user = Auth::user();
$s3 = Storage::disk('s3');
$storage = Storage::disk('s3')->url('/');
$path = 'public/docs/user_docs/'.$user->id.'/';
$csvFile = tmpfile();
$csvPath = stream_get_meta_data($csvFile)['uri'];
$fd = fopen($csvPath, 'w');
$columns = array('First Name', 'Email Address');
$data = array(
'First Name' => $user->first_name,
'Email Address' => $user->email,
);
fputcsv($fd, $columns);
fputcsv($fd, $data);
fclose($fd);
$s3->putFileAs('', $csvPath, $path.$user->ein.'.csv');
Today I have fixed it with this snipe:
// output up to 5MB is kept in memory, if it becomes bigger it will
// automatically be written to a temporary file
$csv = fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+');
fputcsv($csv, array('blah','blah'));
rewind($csv);
$output = stream_get_contents($csv);
// Put the content directly in file into the disk
Storage::disk('myDisk')->put("report.csv", $output);
This code is easy and functional, use Laravel Storage Class
https://laravel.com/docs/9.x/filesystem#main-content
use Illuminate\Support\Facades\Storage;
// data array
$results = [
['id' => 0, 'name' => 'David', 'parent' => 1],
['id' => 1, 'name' => 'Ron', 'parent' => 0],
['id' => 2, 'name' => 'Mark', 'parent' => 1]
];
// create a variable to store data
$pages = "id,name,parent\n"; // use " not ' or \n not working
// use foreach to data
foreach ($results as $where) {
$pages .= "{$where['id']},{$where['name']},{$where['parent']}\n";
}
// use Fecades Laravel Storage
Storage::disk('local')->put('file.csv', $pages);
I'm trying to use this: Response::download() to make a download of a file, I'm using Laravel 4, here my code:
public function download_file($file)
{
$file = 'myfile.pdf';
//-- public/docs/myfile.pdf
$path = public_path(). '/docs/' . $file;
$headers = array(
'Content-Type' => 'application/pdf',
);
return Response::download($path, $file, $headers);
}
The error I got:
The file "C:\Users\myuser\Workbench\Web\sites\mysite\public/docs/myfile.pdf" does not exist
What did I went wrong?
Thanks!
I'm trying to zip files selected by the user but for some reason I'm getting this error.
I'm using laravel 4.2
Here is the portion of code where the error is originating from.
$zip_name = 'dris-sweet-16-pictures.zip';
$zip = new ZipArchive();
$zip->open($zip_name, ZipArchive::CREATE);
foreach ($lg_img as $img) {
$zip->addFile(public_path().'/'.$img);
}
Response::download($zip, $zip_name, array(
'content-type' => 'application/zip',
'Content-disposition:' => 'attachment; filename=filename.zip',
'Content-Length:' => filesize($zip_name)
));
$zip->close();
As described here : http://laravel.com/docs/responses#special-responses,
the arguments for this method are in the following order :
Response::download($pathToFile, $name, $headers);
In your code, you are passing $zip, your ZipArchive as the path to the file but the method expect here a string, so the path to your file on the disk.
Cheers.
I am using PHP to create a simple .csv from database entries in Laravel, here's a little sample of the code:
$file = fopen(storage_path('file.csv'), 'w');
//$printer = array from database
foreach ($printer as $row) {
fputcsv($file, $row);
}
fclose($file);
//$formname = Object values
$headers = array(
'Content-Type: text/csv',
'Content-Length: ' . filesize(storage_path('file.csv')),
'Content-Disposition: attachment; filename="'.$formname->name.'.csv"'
);
return Response::download(storage_path('file.csv'), $formname->name.'.csv', $headers);
All pretty standard and work's fine for me, but my Client is using OS X 10.9.3 & Safari 7.0.4 and each download is given a .txt extension and I can't find a way to stop it from either server or client side. (so it downloads as file.csv.txt)
I have searched Google but can only find other users with the problem - no solution, the code above is already edited using suggestions found on Stackoverflow:
1. laravel adding .txt on the downloaded file
2. How to use the CSV MIME-type?
Can anyone tell me where this problem arises and how to fix it?
And is there anywhere I can test the download as I only have Windows and the testing websites I use only provide visual renders.
Also: The client has assured me he can download .csv's from other sources without this problem
As I can see Symfony iterates through the headers as key-value pairs:
public function __construct(array $headers = array())
{
foreach ($headers as $key => $values) {
$this->set($key, $values);
}
}
And then sets them this way:
if (true === $replace || !isset($this->headers[$key])) {
$this->headers[$key] = $values;
} else {
$this->headers[$key] = array_merge($this->headers[$key], $values);
}
So if you only have values in the $headers array with numeric indexes, the result might be unexpected. Try to change your code to this:
$headers = array(
'Content-Type' => 'text/csv',
'Content-Length' => filesize(storage_path('file.csv')),
'Content-Disposition' => 'attachment; filename="'.$formname->name.'.csv"'
);
I have searched for creating pdf file in symfony 2.3 but was not successful. I've got 2 bundle
Knp snapy bundle and another is
psliwa / PHPPdf
My task is just download pdf file on click. For this I have given the link in html.twig like
Download file
In pdf action I am generating the PDF file
In knp snapy bundle I am doing:
$html = $this->renderView('MyBundle:Foo:bar.html.twig', array(
'some' => $vars
));
return new Response(
$this->get('knp_snappy.pdf')->getOutputFromHtml($html),
200,
array(
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="file.pdf"'
)
);
And got error
The exit status code '1' says something went wrong: stderr: "The
system cannot find the path specified.
Is wkpdftohtml necessary for installation if YES then how can I install on sharing based hosting.
In psliwa / PHPdf I have read the example from:
psliwa/PdfBundle
psliwa/PHPPdf
and got
unable to find twig file
If I change the $format = $this->get('request')->get('_format'); to $format='pdf'; then it show simple html file.
Unable to understand what should I do for completion of task...
Yes. For Knp Snappy Bundle, wkhtmltopdf is required and you need to configure it properly in the config.yml
knp_snappy:
pdf:
enabled: true
binary: /usr/local/bin/wkhtmltopdf #path to wkhtmltopdf binary
options: []
This is an excerpt from a controller in a live shared host environment using psliwa/PHPPdf:
$facade = $this->get('ps_pdf.facade');
$response = new Response();
$this->render('ManaClientBundle:Contact:roster.html.twig', array(
'date' => $found['latestDate'],
'center' => $location,
'roster' => $found['contactSet'],
), $response);
$date = new \DateTime($found['latestDate']);
$filename = str_replace(' ', '', $location) . date_format($date, '_Ymd') . '.pdf';
$xml = $response->getContent();
$stylesheet = $this->renderView('ManaClientBundle:Contact:contact.xml.twig', array());
$content = $facade->render($xml, $stylesheet);
return new Response($content, 200, array
('content-type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename=' . $filename
));