PHPExecel file is empty when send as in attachment - phpexcel

An excel file is created using phpexcel which is saved in the folder with all the data. The same file cannot be send as an attachment in the mail. I would also like to upload the excel in the form in order to make changes.
Please advice. Here is the code.
<?php
//include PHPExcel library
require_once "Classes/PHPExcel.php";
require_once "Classes/PHPExcel/IOFactory.php";
if (!empty($_POST['submit'])) {
//give a filename
$dtime = date('Y-m-d H-i-s');
$dtimeFile = date('Y-m-d-H-i-s');
date_default_timezone_set('Asia/Singapore');
$filename = 'myexcel'.$dtimeFile.'.xls';
$path = __DIR__;
//set headers to download file
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename='.$filename);
// create new PHPExcel object
$objTpl = new PHPExcel;
// set default font
$objTpl->getDefaultStyle()->getFont()->setName('Calibri');
// set default font size
$objTpl->getDefaultStyle()->getFont()->setSize(8);
// create the writer
$objWriter = PHPExcel_IOFactory::createWriter($objTpl, "Excel5");
// writer already created the first sheet for us, let's get it
$objSheet = $objTpl->getActiveSheet();
// rename the sheet
$objSheet->setTitle('My Personal Details');
// let's bold and size the header font and write the header
// as you can see, we can specify a range of cells, like here: cells from A1 to A4
$objSheet->getStyle('A1:C1')->getFont()->setBold(true)->setSize(12);
$objSheet->getStyle('A2:C2')->getFont()->setSize(12);
// write header
$objSheet->getCell('A1')->setValue('Name');
$objSheet->getCell('B1')->setValue('Email');
$objSheet->getCell('C1')->setValue('Location');
// we could get this data from database, but for simplicty, let's just write it
$objSheet->getCell('A2')->setValue(stripslashes($_POST['name']));
$objSheet->getCell('B2')->setValue(stripslashes($_POST['email']));
$objSheet->getCell('C2')->setValue(stripslashes($_POST['location']));
// // autosize the columns
// $objSheet->getColumnDimension('A')->setAutoSize(true);
// $objSheet->getColumnDimension('B')->setAutoSize(true);
// $objSheet->getColumnDimension('C')->setAutoSize(true);
// $objSheet->getColumnDimension('D')->setAutoSize(true);
$objWriter->save('php://output');
$to = "cloudinnovates#hotmail.com";
$subject = $filename;
$from = "shabs0#hotmail.com";
$headers = "From: $from\r\n";
$headers .= "MIME-Version: 1.0\r\n"
."Content-Type: multipart/mixed; boundary=\"1a2a3a\"";
$message .= "If you can see this MIME than your client doesn't accept MIME types!\r\n"
."--1a2a3a\r\n";
$message .= "Content-Type: text/html; charset=\"iso-8859-1\"\r\n"
."Content-Transfer-Encoding: 7bit\r\n\r\n"
."Attached is the file number \"".$filename."\"\r\n\r\n"
."--1a2a3a\r\n";
$file = $path.$filename;
$file_size = filesize($file);
$handle = fopen($file, "r");
$content = fread($handle, $file_size);
fclose($handle);
$message .= "Content-Type: application/vnd.ms-excel; name=\"".$filename."\"\r\n"
."Content-Transfer-Encoding: base64\r\n"
."Content-Disposition: attachment; filename=\"".$filename."\"\r\n\r\n"
."\r\n"
.chunk_split(base64_encode($content))
."--1a2a3a--";
// Send email
//
$success = mail($to, $subject, $message, $headers);
if (!$success) {
echo "Mail to ".$to." failed .";
} else {
echo "Success : Mail was send to ".$to;
}
}
//*************** upload file ***************//
if (!empty($_POST['btn-upload'])) {
$file = 'file';
$Reader = PHPExcel_IOFactory::createReaderForFile($file);
$Reader->setReadDataOnly(true);// set this, to not read all excel properties, just data
$objXLS = $Reader->load($file);
$value = $objXLS->getSheet(0)->getCell('A1')->getValue();
$objXLS->disconnectWorksheets();
unset($objXLS);
}
?>

I'm not familiar with PHP Excel and have not worked with PHP for a long time, but something stands out to me in your code.
You initialize a variable for the file name
$filename = 'myexcel'.$dtimeFile.'.xls';
and attempt to read the content of the file like this
$file = $path.$filename;
$file_size = filesize($file);
$handle = fopen($file, "r");
$content = fread($handle, $file_size);
fclose($handle);
But you don't appear to actually save your Excel sheet to that file. Rather, you seem to write it to the output stream of the current PHP page.
$objWriter->save('php://output');
Setting the content-disposition header
header('Content-Disposition: attachment;filename='.$filename);
tells the browser opening this PHP page what to do with the data returned by the PHP page, but does not save the file to your local server, so that it can be attached to an email on that server.
You will need to save the Excel file to a location on your local server before it is attached to the email.

Related

HTTPful attach file and json-body in one request

I need to upload files via Rest and also send some configuration with it.
Here is my example code:
$this->login();
$files = array('file'=>'aTest1.jpg');
$data =
array(
'name'=>'first file',
'description'=>'first file description',
'author'=>'test user'
);
$response = Request::post($this->getRoute('test'))
->addHeader('Authorization', "Bearer " . $this->getToken())
->attach($files)
->body(json_encode($data))
->sendsJson()
->send();
I am able to send the file or able to send the body. But it is not working if I try with both...
Any Hint for me?
Regards
n00n
For those coming to this page via Google. Here's an approach that worked for me.
Don't use attach() and body() together. I found that one will clear out the other. Instead, just use the body() method. Use file_get_contents() to get binary data for your file, then base64_encode() that data and place it into the $data as a parameter.
It should work with JSON. The approach worked for me with application/x-www-form-urlencoded mime type, using $req->body(http_build_query($data));.
$this->login();
$filepath = 'aTest1.jpg';
$data =
array(
'name'=>'first file',
'description'=>'first file description',
'author'=>'test user'
);
$req = Request::post($this->getRoute('test'))
->addHeader('Authorization', "Bearer " . $this->getToken());
if (!empty($filepath) && file_exists($filepath)) {
$filedata = file_get_contents($filepath);
$data['file'] = base64_encode($filedata);
}
$response = $req
->body(json_encode($data))
->sendsJson();
->send();
the body() method erases payload content, so after calling attach(), you must fill payload yourself :
$request = Request::post($this->getRoute('test'))
->addHeader('Authorization', "Bearer " . $this->getToken())
->attach($files);
foreach ($parameters as $key => $value) {
$request->payload[$key] = $value;
}
$response = $request
->sendsJson();
->send();

Symfony2 PHPWord response

I am trying to generate a docx document on Symfony2, using the PHPWord bundle.
In my controller, I succeed in returning a docx file, but it is empty, I think it comes from my faulty response format.
public function indexAction($id)
{
$PHPWord = new PHPWord();
$section = $PHPWord->addSection();
$section->addText(htmlspecialchars(
'"Learn from yesterday, live for today, hope for tomorrow. '
. 'The important thing is not to stop questioning." '
. '(Albert Einstein)'
));
// Saving the document
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($PHPWord, 'Word2007');
return new Response($objWriter->save('helloWorld.docx'), 200, array('Content-Type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'));
}
Try this class
<?php
use PhpOffice\PhpWord\IOFactory;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Settings;
use Symfony\Component\HttpFoundation\Response;
class WordResponse extends Response
{
/**
* WordResponse constructor.
* #param string $name The name of the word file
* #param PhpWord $word
*/
public function __construct($name, &$word)
{
parent::__construct();
// Set default zip library.
if( !class_exists('ZipArchive')){
Settings::setZipClass(Settings::PCLZIP);
}
$writer = IOFactory::createWriter($word, 'Word2007');
//Set headers.
$this->headers->set("Content-Disposition", 'attachment; filename="' . $name . '"');
$this->headers->set("Content-Type", 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
$this->headers->set("Content-Transfer-Encoding", 'binary');
$this->headers->set("Cache-Control", 'must-revalidate, post-check=0, pre-check=0');
$this->headers->set("Expires", '0');
$this->sendHeaders();
$writer->save('php://output');
}
}
Then in your controller do:
return new WordResponse($phpWord, "filename.docx");
Thanks a lot for your answer.
I achieve using the 2nd method, which is in my opinion the best.
I just have to return a response, otherwise the file was generated, but stuck in the web directory.
Using this response, everything was fine and a download prompt appeared, with the "full" file.
Here's my code :
$PHPWord = new PHPWord();
$section = $PHPWord->addSection();
$section->addText(htmlspecialchars(
'"Learn from yesterday, live for today, hope for tomorrow. '
. 'The important thing is not to stop questioning." '
. '(Albert Einstein)'
));
// Saving the document
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($PHPWord, 'Word2007');
$filename="MyAwesomeFile.docx";
$objWriter->save($filename, 'Word2007', true);
$path = $this->get('kernel')->getRootDir(). "/../web/" . $filename;
$content = file_get_contents($path);
$response = new Response();
$response->headers->set('Content-Type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
$response->headers->set('Content-Disposition', 'attachment;filename="'.$filename);
$response->setContent($content);
return $response;
PHPWord->save() returns a true value so that would be why your file is not being downloaded. With your return new Response() you are setting the content of your response to true (the result of your save call) which is why your response is empty.
You have 2 (and probably more that I haven't thought of) options to generate and download this file..
1. Save your file to a temp folder and server from there
$filename = sprintf(
'%s%sDoc-Storage%s%s.%s',
sys_get_temp_dir(),
DIRECTORY_SEPARATOR,
DIRECTORY_SEPARATOR,
uniqid(),
'docx'
);
$objWriter->save($filename);
$response = new BinaryFileResponse($filename);
For more info on the BinaryFileResponse see the docs.
2. Ignore Symfony and serve directly via the PHPWord action
$objWriter->save($filename, 'Word2007', true);
exit();
The ->save method provides all of the actions to download the generated file internally (see the code) so all you need to do is set the format and the third parameter to true and it will handle all of the headers for you. Granted it won't be returning a Symfony response but you will be exiting out before you get to that exception.

Symfony Audio Stream with Gaufrette

I am using KnpGaufretteBundle to store audio files. I am able to download a given file to the client like this:
$filename = "Somefilename.mp3";
$fs = $this->filesystemMap->get('media_fs');
$file = $fs->read($filename);
if($file){
//Create And Return Response
$response = new Response();
$disp = $response->headers->makeDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
$variant->getFileName()
);
$response->headers->set('Content-Length', $fs->size($filename));
$response->headers->set('Accept-Ranges', 'bytes');
$response->headers->set('Content-Transfer-Encoding', 'binary');
$response->headers->set('Content-Type', 'application/octet-stream');
$response->headers->set('Content-Disposition', $disp);
$response->setContent($file);
return $response;
}
But now I also want to stream the file to the client, instead of using the attachment content disposition. Basically I want to access it clientside as if I was pointing at an actual mp3 sitting on my server. Does anyone know how this can be done?
I solved this by using the streamwrapper... it was this easy.
$filepath = 'gaufrette://myFileSystemName/'.$filename;
$response = new \Symfony\Component\HttpFoundation\BinaryFileResponse($filepath);

Create a plain HTTP PUT multipart request with a jpg attached

I'm creating a HTTP PUT request manualy. I have the following format
POST http://server.com/id/55/push HTTP/1.0
Content-type: multipart/form-data, boundary=AaB03x
Content-Length: 168
--AaB03x
Content-Disposition: form-data; name="image"; filename="small.jpg"
Content-Type: image/jpeg
Content-Transfer-Encoding: binary
<file content>
--AaB03x--
My question is, how should I fill the "file content" area? If I open a jpeg with TexMate or with cat command line application and I paste the ASCII output, the request does not work.
UPDATE
I'm working with a microprocessor and I can't use C or a high level language I need to manually do the raw request. Do I need to separate with spaces every binary byte read from the file?
In case of saving the jpg into a file in the server side, Do I have to convert the binary stream to ASCII?
I read the binary code of a JPG from my hard drive with a simple php conde:
$filename = "pic.jpg";
$handle = fopen($filename, "rb");
$fsize = filesize($filename);
$contents = fread($handle, filesize($filename));
fclose($handle);
//echo $contents;
for($i = 0; $i < $fsize; $i++)
{
// get the current ASCII character representation of the current byte
$asciiCharacter = $contents[$i];
// get the base 10 value of the current characer
$base10value = ord($asciiCharacter);
// now convert that byte from base 10 to base 2 (i.e 01001010...)
$base2representation = base_convert($base10value, 10, 2);
// print the 0s and 1s
echo($base2representation);
}
whit this code I get a stream of 1 and 0. I can send it including the string of 101010101... to where the tag "file content" of my manually http request is but in the server side I can't visualise the JPG... ¿should I convert it to ASCII again?
SOLUTION
Okay the solution was very simple, I just dumped the ASCII code into the tag "file content" of the http request. Despite I'm using a micro controller I opened a socket with PHP and tested out. The solution was to read the ASCII from the file instead of paste directly the ASCII into the code.
Here a working example of the solution:
<?php
//We read the file from the hard drive
$filename = "pic.jpg";
$handle = fopen($filename, "rb");
$fsize = filesize($filename);
$contents = fread($handle, filesize($filename));
fclose($handle);
$mesage = $contents;
//A trick to calculate the length of the HTTP body
$len = strlen('--AaB03x
Content-Disposition: form-data; name="image"; filename="small.jpg"
Content-Type: image/jpeg
Content-Transfer-Encoding: binary
'.$mesage.'
--AaB03x--');
//We create the HTTP request
$out = "POST /temp/test.php HTTP/1.0\r\n";
$out .= "Content-type: multipart/form-data boundary=AaB03x\r\n";
$out .= "Content-Length: $len\r\n\r\n";
$out .= "--AaB03x\r\n";
$out .= "Content-Disposition: form-data; name=\"image\"; filename=\"small.jpg\"\r\n";
$out .= "Content-Type: image/jpeg\r\n";
$out .= "Content-Transfer-Encoding: binary\r\n\r\n";
$out .= "$mesage\r\n";
$out .= "--AaB03x--\r\n\r\n";
//Open the socket
$fp = fsockopen("127.0.0.1", 8888, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
//we send the message thought the opened socket
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}
//Visualize the query sent
echo nl2br($out);
?>
In the real implementation I will simple read directly from the memory of the microcontroler just as I did in the php
You are mistyping the last boundary, it should have been:
--AaB03x--
You need to have an OutputStream of your outcoming connection and use this Stream to write ALL BYTES that you have read from the file.
If you used C#. You can check this: Sending Files using HTTP POST in c#
For Java:
Image writing over URLConnection
how to send data with file upload to the server
HttpURLConnection POST, conn.getOutputStream() throwing Exception

Download files directly to my server

Is there a way to download files directly to my web host? Let's say I want to download a video file from a site and upload it in to my website again. Instead of downloading it to my PC and uploading, Is there a way to do that easily?
Thank you!
I'm using this script now :)
`
if (!isset($_POST['submit'])) die();
// folder to save downloaded files to. must end with slash
$destination_folder = 'downloads/';
$url = $_POST['url'];
$name = $_POST['name'];
$ext = $_POST['extention'];
$newfname = $destination_folder . $name . '.' . $ext;
$file = fopen ($url, "rb");
if ($file) {
$newf = fopen ($newfname, "wb");
if ($newf)
while(!feof($file)) {
fwrite($newf, fread($file, 1024 * 8 ), 1024 * 8 );
}
}
if ($file) {
fclose($file);
}
if ($newf) {
fclose($newf);
}
echo 'File saved as '. $newfname
?>`

Resources