PHPEXCEL set UTF-8 encode - php

I have headers:
header('Content-Type: text/html; charset=UTF-8');
header("Content-type: application/octetstream");
header('Content-Disposition: attachment; filename="export.csv"');
but decoding not work correct if I have word in database "Pagrindinė" in excel show "PagrindinÄ", what is wrong with my headers ?

What is wrong with my headers ?
Nothing, your headers are looking fine.
What is wrong with Excel?
The user who opens the file in Excel needs to tell Excel that the file is in UTF-8 encoding. Direct that user to contact the vendor of the software it uses for her/his support options.
Users of LibreOffice or a derivate of it do not have that problem btw., so one solution is to tell those to install a suite of such, open the CSV file and save it as Excel file for example.
Or you directly create the Excel file on your server.

Maybe if you change the format text encoding of your .php file when you save it, to Unicode (UTF-8). It works for me.
Hope it helps.

try this:
header('Content-Transfer-Encoding: binary');
header("Content-Type: application/octet-stream");
header("Content-Transfer-Encoding: binary");
header('Expires: '.gmdate('D, d M Y H:i:s').' GMT');
header('Content-Disposition: attachment; filename = "Export '.date("Y-m-d").'.xls"');
header('Pragma: no-cache');
//these characters will make correct encoding to excel
echo chr(255).chr(254).iconv("UTF-8", "UTF-16LE//IGNORE", $out);

Related

Create PDF file from Raw PDF Content

I am getting raw PDF data from an API and want to create PDF file from this data.
The raw PDF data looks like:
%PDF-1.5
%
....................
....................
%%EOF
I created PDF file with above content with the help of PHP file handling functions and it seems file is created successfully. However when newly created PDF is opened, it simply shows blank white page (without any content). If same file is opened in IDE (like notepad++), it shows the raw content written in correctly.
I even tried PHP header with different params with no luck. I also tried using DOMPDF library and that still doesn't help either.
I guess there is some extra information in raw content (maybe header, filename etc.) and I need to get actual content from it but I have no idea how?
Can anyone guide me what I am missing here?
Thanks!
try following script i think you miss some header:
$path = /path/to/yourfilename.pdf;
$content = <your raw pdf data>;
//put your content to file
file_put_contents($path, $content);
header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
// force download
header('Content-Type: application/force-download');
header('Content-Type: application/octet-stream', false);
header('Content-Type: application/download', false);
header('Content-Disposition: attachment; filename="'.basename($path).'";');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.filesize($path));
header('Content-Type: application/pdf', false);
readfile($path);
exit();

PHP force downloading .xlsx file corrupt

I am working on a site that allows teachers to upload documents and students download them. However, there is a problem. Microsoft Word (.docx) files download perfectly, but when downloading an excel (xlsx) file, excel gives a "This file is corrupt and cannot be opened" dialog. Any help with this would be greatly appreciated!
My download code is as follows:
case 'xlsx':
header('Content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Pragma: no-cache');
readfile('./uploads/resources/courses/' . $filename);
break;
I have this problem and was the BOM.
How to notice it
unzip: Checking the output file with unzip, I saw a warning at the second line.
$ unzip -l file.xlsx
Archive: file.xlsx
warning file: 3 extra bytes at beginning or within zipfile
...
xxd (hex viewer): I saw the first 5 bytes with the following command
head -c5 file.xlsx | xxd -g 1
0000000: ef bb bf 50 4b PK...
Notice the 3 first bytes ef bb bf that's BOM!
Why?
Maybe a php file with BOM or a previous output from a library.
You have to find where is the file or command with the BOM, In my case and right now, I don't have time to find it, but I solve this with output buffer.
<?php
ob_start();
// ... code, includes, etc
ob_get_clean();
// headers ...
readfile($file);
this works fine on my local xampp setup regardless of extension so from my point of view no case statement is needed unless i'm missing something
i've tested with docx, accdb, xlsx, mp3, anything ...
$filename = "equiv1.xlsx";
header('Content-type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Pragma: no-cache');
try this:
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Content-Type: application/vnd.ms-excel");
try:
<?
//disable gzip
#apache_setenv('no-gzip', 1);
//set download attachment
header('Content-Disposition: attachment;filename="filename.xlsx"');
//clean the output buffer
ob_clean();
//output file
readfile('filepath/filename.xlsx');
//discard any extra characters after this line
exit;
?>
Try adding a additional header
header('Content-Length: ' . filesize('./uploads/resources/courses/' . $filename));
Probably it's very misleading information given by Windows and has nothing to do with the code, Excel library, or server, and the file itself is a proper one. Windows blocks opening some files downloaded from the Internet (like .xlsx) and instead of asking whether you want to open an insecure file, it just writes that the file is corrupt. In Windows 10, one needs to right-click the file and select "Unblock" (you can read more for example here: https://winaero.com/blog/how-to-unblock-files-downloaded-from-internet-in-windows-10/)

"Excel found unreadable content" warning when opening Excel files made with PHPExcel

I'm trying to download Excel files (xlsx) using PHPExcel as follows.
require_once("../../phpExcel/Classes/PHPExcel.php");
require_once("../../phpExcel/Classes/PHPExcel/IOFactory.php");
$objPHPExcel = new PHPExcel();
$objPHPExcel->getProperties()->setCreator("Tiny")
->setLastModifiedBy("Tiny")
->setTitle("Office 2007 XLSX Test Document")
->setSubject("Office 2007 XLSX Test Document")
->setDescription("Test document for Office 2007 XLSX, generated using PHP classes.");
$objPHPExcel->setActiveSheetIndex(0);
$sheet=$objPHPExcel->getActiveSheet();
$sheet->setCellValue('A1', 'Hello');
$sheet->setCellValue('B2', 'world!');
$sheet->setCellValue('C1', 'Hello');
$sheet->setCellValue('D2', 'world!');
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="test.xlsx"');
header('Cache-Control: max-age=0');
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter->save('php://output');
It works but when I try to open the Excel file, it asks for a confirmation in a conform dialog.
Excel found unreadable content in 'test.xlsx'. Do you want to recover
the contents of this workbook? If you trust the source of this
workbook, click Yes.
I also tried to change the header as follows
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");;
header("Content-Disposition: attachment;filename=test.xlsx");
header("Content-Transfer-Encoding: binary");
It still asks for the same confirmation. What am I doing wrong here, please?
As told by questioning user Tiny on his own comment:
Finally, it worked. I just added exit at the end of my PHP script (at
the end of the first code snippet in the question). Thanks very much
all of you for giving me useful hints.
To give some constructive additional tips on this kind of problems:
A good tip is that you can omit the closing tag ?> on all your PHP script files, that way you know that you're not sending any aditional invisible whitespace at the end of it.
Also enconding PHP script files on UTF-8 on wrongfully configured web server can send an undesirable couple bytes at the begining of the script. Open the PHP file on Notepad++, check if it's UTF-8, and in that case, convert it to ANSI. If that makes it work, check your webserver/php configuration.
Just before the header calls, you can check if headers has been wrongfully sent with:
if ( headers_sent() ) die("**Error: headers sent");
If you can't prevent that some function call sends undesirable strings to the browser, you can "erase" all of it using at the very beginning of your script:
ob_start();
and then, just before the first headers call, use:
ob_clean();
Be careful that with doing so will prevent you for receiving error feedback.
And lastly, as already said, if nothing has to be executed afterwards some point on the script, call exit or die.
Well I had this problem, my solution was changing the header Content-type to :
header('Content-Type: application/openxmlformats-officedocument.spreadsheetml.sheet');
I had before:
header('Content-Type: application/vnd.ms-excel');
and I changed the format to Excel2007, I was using Excel5 for excel 2003 xls format.
I tried all the solutions from this page and all the other pages with the same question but not luck.
So basically, I just changed the output format of my excels and that solved the problem.
This error can also be triggered by serving the file without the Content-Length headers.
Look at the example given here in php.net
Give the active sheet a title:
$sheet->setTitle('Some title string here');
I Put just exit; After
PHPExcel_IOFactory::createWriter($phpExcelObject, 'Excel2007')->save("php://output");
and it work's for me :)
$file_name .= "_".\Carbon\Carbon::now()->format('d_m_Y_H_i').'.xlsx';
// Prepare To Download
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename='.$file_name);
header('Cache-Control: max-age=0');
header('Pragma: public');
PHPExcel_IOFactory::createWriter($phpExcelObject, 'Excel2007')->save("php://output");
exit;
This might help to someone who tries to download excel using https://github.com/Maatwebsite/Laravel-Excel package in laravel with get route with ajax
I got response something like PK ¾#G’D²X ð [Content_Types].xml­”MNÃ0…÷œ"ò%nY „švAa •(0ö¤±êØ–gúw{&i‰#ÕnbEö{ßøyìÑdÛ¸l mð¥‘×ÁX¿(ÅÛü)¿’òF¹à¡;#1_滘±Øc)j¢x/%ê…Eˆày¦ ©QÄ¿i!£ÒKµ y3ÜJ<§œZ1½0?YÙL%zV cäÖIb7؇û‰ìa/lÙ¥P1:«qáríÍjªÊj0A¯–Íuë""íàÙ(Œ ”Á€WìMä)Tjå and much more content
i tried many of the solution but fails
finally i achieved by doing this in onclick event
$(document).on('click','#elementId',function(e){
e.preventDefault();
window.location.assign('your action url'+'?param='+ param_data);
}
my php : 7.4.1 os: Ubuntu 18.04 frameword: Yii2.0.37 I had also this problem and my solution is that I use exit and ob_clean()
$objPHPExcel = new \PHPExcel();
$objPHPExcel->getProperties()->setCreator("Murodjon Abduvohidov")
->setLastModifiedBy("Murodjon Abduvohidov");
$objPHPExcel->getActiveSheet()->getPageSetup()-> setOrientation(\PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE)
->setPaperSize(\PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4);
$objPHPExcel->getActiveSheet()->getSheetView()->setZoomScale(70);
$objPHPExcel->getActiveSheet()->getSheetView()->setZoomScaleNormal(82);
$objPHPExcel->getActiveSheet()->getSheetView()->setView(\PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW);
$objPHPExcel->getActiveSheet()->getPageSetup()->setScale(63);
$objPHPExcel->getActiveSheet()->getPageMargins()->setTop(0.4);
$objPHPExcel->getActiveSheet()->getPageMargins()->setRight(0.4);
$objPHPExcel->getActiveSheet()->getPageMargins()->setLeft(0.4);
$objPHPExcel->getActiveSheet()->getPageMargins()->setBottom(0.4);
$objPHPExcel->getDefaultStyle()->getFont()->setName('Arial');
$objPHPExcel->getDefaultStyle()->getFont()->setSize(10); $objPHPExcel->getActiveSheet()->getCell('A2')->setValue('salom');
$objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');ob_clean();
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="abdulqodir.xlsx"');
header('Cache-Control: max-age=0');
header('Cache-Control: max-age=1');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
header('Pragma: public'); // HTTP/1.0
$objWriter->save("php://output");exit;`

creating excel with Greek characters

i have used the following headers in order to create xls files that contains Greek characters on the fly.
first attempt:
header("Content-Type: application/$file_type;charset=utf-8");
header("Content-Disposition: attachment; filename=$file_name.$file_ending");
header("Pragma: no-cache");
header("Expires: 0");
second attempt:
header("Content-Type: application/$file_type;charset=windows-1253");
header("Content-Disposition: attachment; filename=$file_name.$file_ending");
header("Pragma: no-cache");
header("Expires: 0");
the created file althought it contains the correct Greek characters (viewed with a text editor) when i open it at the ms-excel the Greek characters are shown as sympols.
i have also tried a library that creates xls (open xls binary format) with the same outcome. This library has options to set the codepage and the charset but still nothing.
any ideas?
thanks.
If you're using a library then it should have a function to set the encoding to UTF-8. For example, with PEAR's Spreadsheet_Excel_Writer (http://pear.php.net/package/Spreadsheet_Excel_Writer/redirected), you would do:
<?php
$workSheet = & $workBook -> addWorksheet('Students');
$workSheet -> setInputEncoding('utf-8');
?>
Of course, you must also make sure that your data are actually utf-8 and not ISO-8859-7 or windows-1253 for example.
Be aware that this does not support workbook name changing (ie using 'Μαθητές' instead of 'Students')
I'm not so sure about XLS files but if you'd rather use Excel readable CSV files, use UTF-16 encoding (with BOM) and tabs as separators
header('Content-Description: File Transfer');
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename=export.csv');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
echo chr(255) . chr(254); // Add UTF-16 little-endian BOM
echo mb_convert_encoding("α\tβ\tγ"), 'UTF-16LE', 'UTF-8'); // from UTF-8 to UTF-16

headers to force the download of a tar archive

i have a tar archive on the server that must be downloadable through php. This is the code that i've used:
$content=file_get_contents($tar);
header("Content-Type: application/force-download");
header("Content-Disposition: attachment; filename=$tar");
header("Content-Length: ".strlen($content));
unlink($name);
die($content);
The file is downloaded but it's broken and it can't be open. I think that there's something wrong with headers because the file on the server can be open without problems. Do you know how can i solve this problem?
UPDATE
I've tried to print an iframe like this:
<iframe src="<?php echo $tar?>"></iframe>
And the download works, so i'm sure that there's something missing in headers.
I have used this code when I have had to do it:
function _Download($f_location, $f_name){
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Length: ' . filesize($f_location));
header('Content-Disposition: attachment; filename=' . basename($f_name));
readfile($f_location);
}
_Download("../directory/to/tar/raj.tar", "raj.tar");
//or
_Download("/var/www/vhost/domain.com/httpdocs/directory/to/tar/raj.tar", "raj.tar");
Try that.
Don't use file_get_contents() and then echo or print to output the file. That loads the full contents of the file into memory. A large file can/will exceed your script's memory_limit and kill the script.
For dumping a file's contents to the client, it's best to use readfile() - it will properly slurp up file chunks and spit them out at the client without exceeding available memory. Just remember to turn off output buffering before you do so, otherwise you're essentially just doing file_get_contents() again
So, you end up with this:
$tar = 'somefile.tar';
$tar_path = '/the/full/path/to/where/the/file/is' . $tar;
$size = filesize($tar_path);
header("Content-Type: application/x-tar");
header("Content-Disposition: attachment; filename='".$tar."'");
header("Content-Length: $size");
header("Content-Transfer-Encoding: binary");
readfile($tar_path);
If your tar file is actually gzipped, then use "application/x-gtar" instead.
If the file still comes out corrupted after download, do some checking on the client side:
Is the downloaded file 0 bytes, but the download process seemed to take much longer than it would take for 0 bytes to transfer, then it's something client-side preventing the download. Virus scanner? Trojan?
Is the downloaded file partially present, but smaller than the original? Something killed the transfer prematurely. Overeager firewall? Download manager having a bad day? Output buffering active on the server and the last buffer bucket not being flushed properly?
Is the downloaded file the same size as the original? Do an md5/sha1/crc checksum on both copies. If those are the same, then something's wrong with the app opening the file, not the file itself
Is the downloaded file bigger than the original? Open the file in notepad (or something better like notepad++ which doesn't take years to open big fils) and see if any PHP warnings messages, or some invisible whitespace you can't see in your script got inserted into the download at the start or end of the file.
Try something like the following:
$s_filePath = 'somefile.ext';
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'. s_filePath.'"');
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');
header('Cache-control: private');
header('Pragma: private');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header("Content-Length: ".filesize($s_filePath));
$r_fh = fopen($s_filePath,'r');
while(feof($r_fh) === false) {
$s_part = fread($r_fh,10240);
echo $s_part;
}
fclose($r_fh);
exit();
Use Content-Type: application/octet-stream or Content-Type: application/x-gtar
Make sure you aren't echoing anything that isn't the file output. Call ob_clean() before the headers

Categories