I am working on Laravel file attachment. I have to send CSV file as attachment in mail without downloading the file to my server. When I click the submit button it didnot send email with file attachment.
My Controller:
$data["email"] = $request->recipient_email;
$data["subject"] = 'Cashup Report for '. $venue->name;
$data["bodyMessage"] = $venue->name.' from '.$start.' to '.$end ;
$excel_file = Excel::create(uniqid().'Cashups', function($excel) use($transactions,$start,$end,$venue) {
$excel->sheet('New sheet', function($sheet) use($transactions,$start,$end,$venue) {
$sheet->loadView('excel.cashups', array('transactions' => $transactions, 'start'=> $start, 'end' => $end, 'venue' => $venue));
});
});
//Feedback mail to client
Mail::send('emails.cashups_report', $data, function($message) use ($data,$excel_file){
$message->from(config('mail.from.address'));
$message->to($data["email"]);
$message->subject($data["subject"]);
//Attach PDF doc
$message->attachData($excel_file,'cashups-report.xlsx');
});
I dont know where i am going wrong. I have already put much time over this but didn't find any solution.
Any guidence in this regards will be highly appreciated. Thanks
You can achieve your goal using the code below. I tried my level best to explain everything in the comments of the code.
//function to generate the csv to be attached in your email
public function createCSV()
{
$myData = MyModel::where(myConditions)->get(['col1','col2','col3']);
header('Content-Type: text/csv; charset=utf-8');
//header without attachment; this instructs the function not to download the csv
header("Content-Disposition: filename=myCsvFile.csv");
//Temporarily open a file and store it in a temp file using php's wrapper function php://temp. You can also use php://memory but I prefered temp.
$Myfile = fopen('php://temp', 'w');
//state headers / column names for the csv
$headers = array('col_name1','col_name2','col_name3');
//write the headers to the opened file
fputcsv($Myfile, $headers);
//parse data to get rows
foreach ($myData as $data) {
$row=array(
$data->col1,
$data->col2,
$data->col3,
);
//write the data to the opened file;
fputcsv($Myfile, $row);
}
//rewind is a php function that sets the pointer at begining of the file to handle the streams of data
rewind($Myfile);
//stream the data to Myfile
return stream_get_contents($Myfile);
}
second function: this sends the email to receipients with the csv attached
public function sendEmail()
{
Mail::send('path_to_your_view.My_view', array(''),
function($message){
$message->to(explode(',', env('EMAILS')))
->subject('Email Subject')
->attachData($this->createCSV(), "MyfileName.csv");
});
}
/*......¯\_(ツ)_/¯......
It works on my computer*/
Best of luck! :)
Related
I use a mySQL database and have to create some lists in Excel format (xlsx). The Excel sheets must be formated. For csv export I use phpExcel (I know, it is obsolete but still working).
Which add on do I need to create formated Excel sheets from my mySQL database. I use php to create the frontend.
Thanks,
Markus
This is just a copy of the function i use. It just launches the function when a specific $_GET isset. The function creates a xlsx file. If you want to export the file as .csv you can just change the file extension and edit text/xlsm to text/csv
$gg = $db->prepare("SELECT * FROM beta_mails ORDER BY created DESC");
$gg->execute();
$ggg = $gg->get_result();
$gg->store_result();
while ($row = $ggg->fetch_assoc()) {
$data[] = $row;
}
function getprelaunchCSV(){
global $data;
header('Content-Type: text/xlsx; charset=utf-8');
header('Content-Disposition: attachment; filename=data.xlsx');
// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');
// output the column headings
fputcsv($output, array('ID', 'EMAIL', 'OPRETTET'));
foreach ($data as $rowCSV){
fputcsv($output, [$rowCSV["id"], decrypt($rowCSV["email"]), $rowCSV["created"]]);
}
fclose($output);
die();
}
if (isset($_GET["getlist"]) && $_GET["getlist"] == "1") {
echo getprelaunchcsv();
header("Location:admin?success=1");
}
I have a PHP application which generates a set of codes , saves them to MySQL DB and then outputs the same to the user as a downloadable csv file. I also have an echo statement after the code block to convert the PHP array to csv. The echo statement after the convert_to_csv function call instead of outputting to the browser outputs to the file instead and overwrites the first line. How do I get the echo statement to output to the browser instead? The code block is below:
convert_to_csv($newCodesArray,$fileName,',');
echo "Your file was successfully generated";
function convert_to_csv($input_array, $fileName, $delimiter)
{
header('Content-Type: text/csv');
header("Content-Disposition: attachment; filename=\"$fileName\"");
$f = fopen('php://output', 'w');
/* loop through array */
foreach ($input_array as $line) {
/* default php csv handler */
fputcsv($f, $line, $delimiter);
}
fclose($f) or die("Can't close php://output");
}
You have already defined the header as text/csv. So it wont print in the browser as it requires text/html.
Alternatively you can do as following. Copy your function to different file (Ex. csv.php).
<?php
echo "Your file was successfully generated <script> window.location = 'csv.php' </script>";
Now it will print your echo string and start download your csv file.
As Magnus Eriksson commented,
Above code does not checking its really generated successfully or not. We can extend code with AJAX.
<script>
$.ajax('csv.php', {
success: function(data) {
document.write('Your file was successfully generated.');
windows.location = 'csv.php';
},
error: function() {
document.write('Your file generation failed.');
}
});
</script>
Note:- AJAX call will generate file two times.
I leave a simple text for fast reading.
I'm trying to figure out how to send a csv file via sendgrid, csv is used with array, it's
fputcsv($output, array('Column 1', 'Column 2', 'Column 3'));
It's not a real file from server, simply to create file and export data to users.
The problem is... addAttachment or setAttachment returned some errors, they requiere where to find a file from path or directory.
How to attach a file without requesting an existing file from directory via sendgrid?
EDIT:
//Function to generate csv file
private function array2csv($array) {
if (count($array) == 0) {
return null;
}
$lista = $array;
ob_start();
$fp = fopen('php://output', 'w');
foreach ($array as $campos) {
fputcsv($fp, $campos);
}
fclose($fp);
return ob_get_clean();
}
//Call a function to send csv file
public function sendCSVFile(){
$data = $this->reqProducts();
//prepareParams is csv templating and formatting function.
$products = $this->prepareParams($data);
$products = $this->array2csv($products);
$body = "Hello, you have an attached file."
$email = new SendGrid\Email();
$email
->addTo('foo#bar.com')
->setFrom('me#bar.com')
->setSubject($body)
->setText($body)
->setHtml('<strong>Hello World!</strong>')
->addAttachment($products);
}
Error output is:
I'm trying to implement a tool to export data from a research website as a csv file. In my download controller, I have:
public function export(){
$data = array(
array('Name', 'Age', 'City'),
array('Philippe', '23', 'Palo Alto'),
array('John', '30', 'San Francisco'),
array('Paul', '20', 'Los Angeles')
);
header('Content-type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=data.csv');
$fp = fopen('php://output', 'w');
foreach( $data as $line ) {
fputcsv( $fp, $line );
}
fclose($fp);
}
and from my view, I do:
function download() {
$('#download').empty().html('<img src="<?php echo base_url();?>/images/loader.gif" />');
$.post('<?php echo base_url();?>/index.php/download/export');
}
and download() is fired up when the user click to a button with a onclick='download()'.
However, I'm not seen the file being downloaded, nor a error message. When I look into my firebug console, I see:
200 OK 29ms jquery.min.js (line 4) HeadersPostResponseCookies
Name,Age,City Philippe,23,"Palo Alto" John,30,"San Francisco"
Paul,20,"Los Angeles"
What am I missing?
Thanks
You don't actually want an AJAX request here. You want to redirect your user to the file with:
window.location = '<?php echo base_url();?>/index.php/download/export';
The AJAX request is telling the server to send the data back to the script's success method. Since it's a download, the redirect won't make you leave the page so you can use this method without confusing your user.
I'm trying to send a .CSV file with PHP. The file is written to disk before it's sent but when I try to attach the file with file_get_contents(); the structure of the .CSV isn't preseved yet when try and send the file that's created before it's sent I get a resource id (#183) so how can i attach a file which the user can open as a .CSV file? I've made sure the mime type and headers are correct
EDIT
if(!file_exists(_PS_ORDERS_DIR_.$orderDate.'/'.$file_name.'.csv'))
{
if($file = fopen (_PS_ORDERS_DIR_.$orderDate.'/'.$file_name.'.csv', 'x+'))
{
foreach ($list as $fields)
{
fputcsv($file, $fields);
}
$attachment['mime'] = 'application/vnd.ms-excel';
$attachment['content'] = file_get_contents(_PS_ORDERS_DIR_.$orderDate.'/'.$file_name.'.csv');
$attachment['name'] = $order.'order';
Mail::Send(1, 'order_conf', 'Order CSV Attachment', $success, 'dan.farr#gmail.com', CakeToppers, NULL, NULL, $attachment);
return true;
}
If you are using Swift Mailer, there is no need for file_get_contents(), you can just attach the file directly.
From the Swift Mailer documentation:
//Create the attachment
// * Note that you can technically leave the content-type parameter out
$attachment = Swift_Attachment::fromPath('/path/to/image.jpg', 'image/jpeg');
//Attach it to the message
$message->attach($attachment);
So for you that would be:
$attachment = Swift_Attachment::fromPath(_PS_ORDERS_DIR_.$orderDate.'/'.$file_name.'.csv', 'application/vnd.ms-excel');
//Attach it to the message
$message->attach($attachment);