Save formated xml to file in PHP - php

I know that there are a ton of questions about this here but every answer i tried didn't fixed my problem
Problem
I have xml saved on a string and i want so save it to a file but don't want the xml to be in a single line i want to write to the file in pritty print
Also there is a bigger problem with this the instead of the this " it shows this " since this file will be loaded in a diferent website i can't have "
Note that the $content variable has " not "
I know that \n doesn't matter but to make it easier to analize the generated xml file i need the xml to be formated
this is what i am using
$dirname = "temp/" . uniqid();
mkdir($dirname);
$filename = $dirname . "/gen.xml";
$doc = new DomDocument($content);
$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;
$doc->save($filename);
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Length: ". filesize("$filename").";");
header("Content-Disposition: attachment; filename=gen.xml");
header("Content-Type: application/octet-stream; ");
header("Content-Transfer-Encoding: binary");
readfile($filename);
$fh = fopen($filename, 'a');
fclose($fh);
unlink($filename);
rmdir($dirname);
I also tried
header("Content-type: text/xml");
and
file_put_contents

DomDocument's constructor does not accept an xml string - rather, an optional version and encoding.
What you probably want is to load your $content xml string instead:
$doc = new DOMDocument();
$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;
$doc->loadXML($content);
$doc->save($filename);

Related

PHP: output a docx file from html

Previously I want to output a doc file it is fine.
But when I change to docx then it told me can't open docx because found a problem with its contents/the file is corrupt.
If I take out 'echo', then no error occurs but with empty content.
Here is my code:
$fileName = $m_year . "-" . $m_month . "-" . $m_con_id . " - Monthly Report.docx";
header("Content-type: application/vnd.openxmlformats-officedocument.wordprocessingml.document");
header("content-disposition: attachment;filename=\"". $fileName ."\"");
header('Cache-Control: public');
$content = ets_docMonthlyReportTemplate();
echo $content;
Then I change to vsword, but give me illegal name character. Location: Part:/word/document.xml
require_once '/vsword/VsWord.php';
VsWord::autoLoad();
$doc = new VsWord();
$parser = new HtmlParser($doc);
$content = ets_docMonthlyReportTemplate();
$html= $content;
$parser->parse($html);
echo '<pre>'.($doc->getDocument()->getBody()->look()).'</pre>';
$doc->saveAs($fileName);
Can I just output by header MIME Type?or must apply library?
Thanks.
You need to use a library to accomplish this.
One of the more popular ones is PHPWord
There is also VSword
There are also paid soluitions PHPDocx
readfile($fileName); should solve it
`require_once '/vsword/VsWord.php';
VsWord::autoLoad();
$doc = new VsWord();
$parser = new HtmlParser($doc);
$content = ets_docMonthlyReportTemplate();
$html= $content;
$parser->parse($html);
echo '<pre>'.($doc->getDocument()->getBody()->look()).'</pre>';
$doc->saveAs($fileName);
header("Content-type: application/vnd.openxmlformats-officedocument.wordprocessingml.document");
header("content-disposition: attachment;filename=\"". $fileName ."\"");
readfile($fileName);`

php download file: header()

I need some eduction please.
At the end of each month, I want to download some data from my webserver to my local PC.
So, I've written a little script for that, which selects the data from the DB.
Next, I want to download it.
I've tried this:
$file=$month . '.txt';
$handle=fopen($file, "w");
header("Content-Type: application/text");
header("Content-Disposition: attachment, filename=" . $month . '.txt');
while ($row=mysql_fetch_array($res))
{
$writestring = $row['data_I_want'] . "\r\n";
fwrite($handle, $writestring);
}
fclose($handle);
If I run this, then the file is created, but my file doesn't contain the data that I want. Instead I get a dump from the HTML-file in my browser..
What am I doing wrong..
Thanks,
Xpoes
Below script will help you download the file created
//Below is where you create particular month's text file
$file=$month . '.txt';
$handle=fopen($file, "w");
while ($row=mysql_fetch_array($res)){
$writestring = $row['data_I_want'] . "\r\n";
fwrite($handle, $writestring);
}
fclose($handle);
//Now the file is ready with data from database
//Add below to download the text file created
$filename = $file; //name of the file
$filepath = $file; //location of the file. I have put $file since your file is create on the same folder where this script is
header("Cache-control: private");
header("Content-type: application/force-download");
header("Content-transfer-encoding: binary\n");
header("Content-disposition: attachment; filename=\"$filename\"");
header("Content-Length: ".filesize($filepath));
readfile($filepath);
exit;
Your current code does not output a file, it just sends headers.
in order for your script to work add the following code after your fclose statement.
$data = file_get_contents($file);
echo $data;

PHP pass HTML string to create ZIP archive

So I am trying to create a Zip file from 2 strings. 1 is a html string, the other is plain text. So far I only seem to get the text string to work correctly but the file thats supposed to be HTML is just a blank file. Any idea why?
$string1 = $_POST["html_string"];
$string2 = "Some data Some data Some data Some data Some data Some data";
$filename = "test.zip";
$zip = new ZipArchive();
if ($zip->open($filename, ZIPARCHIVE::CREATE)==TRUE) {
$zip->addFromString("string1.html", $string1);
$zip->addFromString("string2.txt", $string2);
$zip->close();
}
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=\"".$filename."\"");
//clearstatcache();
header("Content-Length: ".filesize($filename));
readfile($filename);
unlink($filename);
Thanks for any help.
Tryed your code replacing
$string1 = $_POST["html_string"];
with
$string1 = '<html>
<title></title>
</html>';
and worked.
Are you sure $_POST["html_string"] is not empty? Add var_dump($_POST); to see if there is some data or update your code adding a check at the begining.
if (empty($_POST["html_string"]))
{
echo 'html_string is empty';
exit;
}

PHP readfile() returning corrupted data

In my function I am saving an image decoded from a base64 string:
function saveImage(){
//magic...
define('UPLOAD_DIR', '../webroot/img/');
$base64string = str_replace('data:image/png;base64,', '', $base64string);
$base64string = str_replace(' ', '+', $base64string);
$data = base64_decode($base64string);
$id = uniqid();
$file = UPLOAD_DIR.$id.'.png';
$success = file_put_contents($file, $data);
}
The above function works properly and the images are saved and not corrupted in the specified folder.
In the next function I am now trying to force download the image to a user:
function getChart($uniqid= null){
if($uniqid){
$this->layout = null;
header("Content-type: image/png");
header("Content-Disposition:attachment;filename='".$uniqid.".png'");
readfile('../webroot/img/'.$uniqid.'.png');
exit;
} else exit;
}
Image downloaded from the server is corrupted and cant be displayed. After opening the downloaded file in a text editor I noticed that a new line character is added at the very top. After deleting the character and saving the file it opens properly and is being displayed properly.
How can I fix this?
What you describe can have multiple issues that are hidden until you actually open the downloaded file.
Instead make your code more robust and check pre-conditions, here if headers have been send already and to clean any possible existing output buffer and give error if that is not possible:
function getChart ($uniqid = null) {
if (!$uniqid) exit;
$this->layout = null;
if (headers_sent()) throw new Exception('Headers sent.');
while (ob_get_level() && ob_end_clean());
if (ob_get_level()) throw new Exception('Buffering is still active.');
header("Content-type: image/png");
header("Content-Disposition:attachment;filename='".$uniqid.".png'");
readfile('../webroot/img/'.$uniqid.'.png');
exit;
}
header("Content-length: $file_size")
This header tells the browser how large the file is. Some browser need it to be able to download the file properly. Anyway it's a good manner telling how big the file is. That way anyone who download the file can predict how long the download will take.
header("Content-type: $file_type")
This header tells the browser what kind of file it tries to download.
header("Content-Disposition: attachment; filename=$file_name");
This tells the browser to save this downloaded file under the specified name. If you don't send this header the browser will try to save the file using the script's name.
BUT you need to flush buffer, with flush(); or in your case with ob_flush(); right above first exit;
check if you are outputing something before calling readfile:
// add ob_start() at the very top of your script
function getChart($uniqid= null){
echo strlen(ob_get_clean()); die(); // if it's not 0 then you are definetly echoing something
if($uniqid){
$this->layout = null;
header("Content-type: image/png");
header("Content-Disposition:attachment;filename='".$uniqid.".png'");
readfile('../webroot/img/'.$uniqid.'.png');
exit;
} else exit;
}
EDIT (to force download):
function getChart($uniqid= null){
if($uniqid){
$image = $uniqid;
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=" . $image);
header("Content-Type: image/jpg");
header("Content-Transfer-Encoding: binary");
readfile($image);
} else exit;
}
getChart("060620121945.jpg");
Try this (just to render image):
function getChart($uniqid= null){
if($uniqid){
$mime_type = "image/png";
$content = file_get_contents('../webroot/img/'.$uniqid.'.png');
$base64 = base64_encode($content);
return ('data:' . $mime_type . ';base64,' . $base64);
} else exit;
}
I have had this problem several times. Here's the solution that I used:
Almost always it turned out that I had forgotten to turn off unicode BOM encoding in my download.php file which adds something to the front of the downloaded file and therefore corrupts it.
So the solution is to turn off unicode BOM in download.php.
Just use ob_clean(); before readfile()

Auto download the file attachment using PHPWord

I'm trying to use PHPWord to generate word documents. And the document can be generated successfully. But there is a problem where my generated word document will be saved on the server. How can I make it available to download straight away?
Sample:
$PHPWord = new PHPWord();
//Searching for values to replace
$document = $PHPWord->loadTemplate('doc/Temp1.docx');
$document->setValue('Name', $Name);
$document->setValue('No', $No);
$document->save('php://output'); //it auto save into my 'doc' directory.
How can i link to the header to download it as follows:
header("Content-Disposition: attachment; filename='php://output'"); //not sure how to link this filename to the php://output..
Kindly advise.
php://output is a write-only stream, that writes to your screen (like echo).
So, $document->save('php://output'); will not save the file anywhere on the server, it will just echo it out.
Seems, $document->save, doesn't support stream wrappers, so it literally made a file called "php://output". Try using another file name (I suggest a temp file, as you just want to echo it out).
$temp_file = tempnam(sys_get_temp_dir(), 'PHPWord');
$document->save($temp_file);
In the header, the filename field is what PHP tells the browser the file is named, it doesn't have to be a name of a file on the server. It's just the name the browser will save it as.
header("Content-Disposition: attachment; filename='myFile.docx'");
So, putting it all together:
$PHPWord = new PHPWord();
//Searching for values to replace
$document = $PHPWord->loadTemplate('doc/Temp1.docx');
$document->setValue('Name', $Name);
$document->setValue('No', $No);
// // save as a random file in temp file
$temp_file = tempnam(sys_get_temp_dir(), 'PHPWord');
$document->save($temp_file);
// Your browser will name the file "myFile.docx"
// regardless of what it's named on the server
header("Content-Disposition: attachment; filename='myFile.docx'");
readfile($temp_file); // or echo file_get_contents($temp_file);
unlink($temp_file); // remove temp file
$objWriter = PHPWord_IOFactory::createWriter($PHPWord, 'Word2007');
$filename = 'MyFile.docx';
$objWriter->save($filename);
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.$filename);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($filename));
flush();
readfile($filename);
unlink($filename); // deletes the temporary file
exit;
This is work for me:
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007', $download = true);
header("Content-Disposition: attachment; filename='File.docx'");
$objWriter->save("php://output");
now whit Ver 0.13.0
https://github.com/PHPOffice/PHPWord
<?
require_once "../include/PHPWord-develop/bootstrap.php";
$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('template.docx');
$templateProcessor->setValue('var01', 'Sun');
$templateProcessor->setValue('var02', 'Mercury');
//#####################################################
// Save File
//#####################################################
//#####################################################
header("Content-Disposition: attachment; filename='output01.docx'");
$templateProcessor->saveAs('php://output');
//#####################################################
//#####################################################
?>
A simple solution for Laravel based on #user3214824 answer.
// ...
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($PHPWord, 'Word2007');
$doc_name = 'fileName.docx';
$objWriter->save($doc_name); // saving in the public path just for testing
return response()->download(public_path($doc_name))->deleteFileAfterSend(true);
Sorry this came in later. I stumbled on this while trying to solve the same problem. I was able to get it working on Laravel 5 using below:
$file_dir = $template_upload_dir.DIRECTORY_SEPARATOR.'filename.docx';
$tags = array();
if (file_exists($file_dir)) {
$templateProcessor = new TemplateProcessor($file_dir);
$tags = $templateProcessor->getVariables();
$replace = array('');
$templateProcessor->setValue($tags, $replace);
$save_file_name = $fullname.'-'.$inv_code.'-'.date('YmdHis').'.docx';
$templateProcessor->saveAs($save_file_name);
return response()->download($save_file_name)->deleteFileAfterSend(true);
}
Hope it helps someone!!!
// Save File
$objWriter = PHPWord_IOFactory::createWriter($PHPWord, 'Word2007');
header("Content-Disposition: attachment; filename='myFile.docx'");
$objWriter->save("php://output");

Categories