I have stored some multiple attachments in my database, in one column by serializing the Attachments data through code:
$files = array(
'file1' => base64_encode(file_get_contents('back.jpg')),
'file2' => base64_encode(file_get_contents('email.jpg')),
'file3' => base64_encode(file_get_contents('web.jpg')),
);
// serialize
$filesData = serialize($files);
Now, in another php page, i am getting the files to download , in that i m UNserializing the above files data, getting them from the database column "Data"
Using the following code to unserialize data, but it seems that the data is not unserailized, I have saved three pics, and when i retrive them, i get a .txt file downloaded, in which written there "Array"
if($result->num_rows == 1) {
$row = mysqli_fetch_assoc($result);
// Print headers
header("Content-Type: ". $row['mime']);
header("Content-Length: ". $row['size']);
header("Content-Disposition: attachment; filename=". $row['name']);
$files = unserialize($row['data']);
echo $files;
}
$files is an array containing the three files, what do you expect?
"Array" is the result of the string cast from echo.
try echo $files['file1'] etc..
Related
I'm trying to export nationality data into CSV. My nationality data are stored in an array. However, when i export it out, my CSV output show this error "Warning: fputcsv() expects parameter 2 to be array". Can I know how i can show my nationality data in a csv column?
my code:
$filename = "nationality_list.csv"; // Create file name
$array_nat = array('BANGLADESH','CAMBODIA','CHINESE','DUTCH','FILIPINO','FRENCH','GERMAN','INDIAN','INDONESIA','ITALY','JAPANESE','KOREAN','LITHUANIAN','MALAYSIA','MYANMAR','NEW ZEALAND','RUSSIAN','SINGAPOREAN','SRI LANKAN','THAILAND','UK','USA');
$f = fopen('php://memory', 'w');
$fields = array('Nationality_list');
fputcsv($f, $fields);
foreach($array_nat as $nat){
fputcsv($f, $nat);
}
//move back to beginning of file
fseek($f, 0);
//set headers to download file rather than displayed
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="' . $filename . '";');
//output all remaining data on a file pointer
fpassthru($f)
Desired output in CSV
Try this:
fputcsv($f, [$nat]);
fputcsv expects an array because a row consists of n columns. 1 in your case :)
I create a xml file based on information from my database (xmltv format). These xml files can be quite big - 25-70mb is normal. Now i create the xml file on the fly like this:
$xmlWriter = new XMLWriter();
$xmlWriter->openURI('php://output');
and flush through the loop to prevent memory overflow. I also set headers to push the content as download:
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $config->filename . '.xml"');
I would like to be able to zip/gzip the xml because of the size. Is this possible on the fly? I have used PHPZip before, which works good with files, but i dont know if i can write the xml output directly to the zip?
If I have understood correctly, the goal is to create gzip compressed data dynamically, without creating a file on the server. This is possible with deflate_init and deflate_add, but requires PHP 7.
$gzip = deflate_init(ZLIB_ENCODING_GZIP, array('level' => 9));
$data = deflate_add($gzip, "my", ZLIB_NO_FLUSH);
$data .= deflate_add($gzip, "data", ZLIB_FINISH);
With deflate_add we can add more data any number of times (the mode should be ZLIB_FINISH for the last chunk).
We can adjust this method using XMLWriter::openMemory (stores the data in memory) and XMLWriter::flush, to zip the xml elements as they are produced, and create the contents of a .gz file on the fly. For example this code:
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="file.gz"');
$xmlWriter = new XMLWriter();
$xmlWriter->openMemory();
$xmlWriter->startDocument('1.0', 'UTF-8');
$gzip = deflate_init(ZLIB_ENCODING_GZIP, array('level' => 9));
for ($i = 0; $i < 10; $i++) {
$xmlWriter->writeElement("element", $i);
$data = $xmlWriter->outputMemory();
echo deflate_add($gzip, $data, ZLIB_NO_FLUSH);
}
echo deflate_add($gzip, "", ZLIB_FINISH);
creates xml elements, compresses and outputs them one by one, without using too much memory or any files.
I have some php code that connects to a MSSQL, looks up some values and retrieves a file that is stored in binary format. The table has the filename, header and the binary data. Presently my code is downloading the file as expected however, if there is a space in the filename, the name is cut short, as if the space is acting as a delimeter. e.g. value in db "This is an example file.pdf" outputted filename "This" and the browser recognises the pdf type.
My somewhat functional code is below:
/* Retrieve and display the data.
The return data is retrieved as a binary stream. */
if ( sqlsrv_fetch( $stmt ) )
{
$noticeID = sqlsrv_get_field( $stmt, 0, SQLSRV_PHPTYPE_INT);
$filename = sqlsrv_get_field( $stmt, 1, SQLSRV_PHPTYPE_STRING("UTF-8"));
$header = sqlsrv_get_field( $stmt, 2, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY));
$download = sqlsrv_get_field( $stmt, 3, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY));
header('Content-Type: '.$header);
header("Content-Disposition: attachment; filename=$filename");
echo "Your file, $filename is ready for download";
fpassthru($download);
}
else
{
echo "Error in retrieving data.</br>";
print_r( sqlsrv_errors(), true);
}
I suspect that the issue is that the filename is stored as a VARCHAR(255) in the DB and somehow is breaking the "Content-Disposition" header line. Research brought me to this page but it isn't very clear on how to handle VARCHAR and when I try and "hack" it by guessing (see below) and get a filename "index.php" (although it does download the file)
$filename = sqlsrv_get_field( $stmt, 1, SQLSRV_PHPTYPE_VARCHAR);
I've also tried this in place of the faulty header line:
$filename = sqlsrv_get_field( $stmt, 1, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY)))
It still cuts off the filename. If there is no space in the filename, the code executes perfectly.
BONUS: does anyone know how I could save the file to the filesystem rather than having a download dialog? This code is proof of concept for a data migration script I'm writing and that would also be very helpful :)
Please try the following: concatenate the header as follows:
header('Content-Disposition: attachment; filename="'."$filename".'"');
And save the file via:
function file_put_contents()
I have troble geting this work and I can't figure it out what is the issue.
I download a xls file, but it doesent opens.
I had a mysql script like this, working, and I tried to convert it into mysqli and probably something is wrong...
Thanks in advance
$sqlExp = "SELECT * FROM table";
$countQryExp = mysqli_query($link, $sqlExp );
$filename = "sampledata.xls"; // File Name
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Content-Type: application/vnd.ms-excel");
$flag = false;
while($row=mysqli_fetch_array($countQryExp,MYSQLI_ASSOC))
{
if(!$flag) {
// display field/column names as first row
echo implode("\t", array_keys($row)) . "\r\n";
$flag = true;
}
echo implode("\t", array_values($row)) . "\r\n";
}
There's a lot more to generating an Excel file than giving it a content type of application/vnd.ms-excel. Excel is a very particular format, whereas you're generating a TSV file - tab separated values, and in a pretty breakable manner (what happens if someone puts a \t in one of your site's fields, or a new line?).
If you want to generate real Excel files, you'll want one of the various libraries for doing so. If a CSV/TSV are fine, just export a .csv/.tsv file with proper headers.
I'm having a bit of trouble exporting a csv file that is created from one of my mysql tables using php.
The code I'm using prints the correct data, but I can't see how to download this data in a csv file, providing a download link to the created file. I thought the browser was supposed to automatically provide the file for download, but it doesn't. (Could it be because the below code is called using ajax?)
Any help greatly appreciated - code below, S.
include('../cofig/config.php'); //db connection settings
$query = "SELECT * FROM isregistered";
$export = mysql_query($query) or die("Sql error : " . mysql_error());
$fields = mysql_num_fields($export);
for ($i = 0; $i < $fields; $i++) {
$header .= mysql_field_name($export, $i) . "\t";
}
while ($row = mysql_fetch_row($export)) {
$line = '';
foreach ($row as $value) {
if ((!isset($value) ) || ( $value == "" )) {
$value = "\t";
} else {
$value = str_replace('"', '""', $value);
$value = '"' . $value . '"' . "\t";
}
$line .= $value;
}
$data .= trim($line) . "\n";
}
$data = str_replace("\r", "", $data);
if ($data == "") {
$data = "\n(0) Records Found!\n";
}
//header("Content-type: application/octet-stream"); //have tried all of these at sometime
//header("Content-type: text/x-csv");
header("Content-type: text/csv");
//header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=export.csv");
//header("Content-Disposition: attachment; filename=export.xls");
header("Pragma: no-cache");
header("Expires: 0");
echo 'Download Exported Data'; //want my link to go in here...
print "$header\n$data";
In essence, you can't output the CSV file and the link to it in one go. (You need to introduce the concept of a page "mode" and activate the download mode via a ...pagename.php?mode=download or similar. You could then use PHP's switch statement to switch on $_GET['mode'] in your script.)
That said, the text/csv content type header you were using is correct, although you may also want to output the Content-Length and Content-Disposition headers. After you've output the file data, also be sure to stop any additional script processing via PHP's exit function.
Additionally, it would probably be a lot less hassle (and will certainly be faster/more memory efficient) to use MySQL SELECT ... INTO OUTFILE facility (if you have the permissions) rather than use PHP to gather the data.
You can't have text and a download on the same page. You need to have a link to the download area, which could just be a GET parameter leading to a function, which then does all the processing, displays headers, and echoes the content of the CSV.
For example, you could have Click here to download CSV, then in your code have if ($_GET['action'] === 'download'), get the data from the database, format it, send the headers, and echo the data. And then die(), because that part of the script can accomplish no more.
You should not put the link in the same file that generates the csv, as the link will not be in the csv itself!
Do something like:
Download CSV
and it should work
Three things to consider:
You're sending headers indicating that the user is going to be downloading a CSV file, but then you send create a link to download it? This isn't correct, you should be linking to this page, and then only outputting the CSV data itself after the headers.
MySQL has the ability to generate CSV output, and you should definitely take advantage of this instead of trying to do it yourself. You can use SELECT INTO ... OUTFILE to do this.
If you must create the CSV using PHP, please use fputcsv to do so. This will handle all the complications of CSV such as escaping and proper formatting. Since fputcsv writes to a file, you could either write it to a temporary file and then output it after you send your headers, or use the following trick to output it directly:
Do this after sending headers:
$fp = fopen('php://output', 'w');
while( $row = mysql_fetch_row( $export ) ) {
fputcsv($fp, $row);
}
I think the mySQL => CSV is common problem which is part of each PHP forum.
I have try to solve this issue in a common way and implement an free export
lib for PHP which is very similar to the Google AppInventor philosophie.
DragDrop and hide the coding stuff.
Use the lib and create your Export via Click&Point.
Common Demos: http://www.freegroup.de/software/phpBlocks/demo.html
Link to editor: http://www.freegroup.de/test/editor/editor.php?xml=demo_sql.xml
worth a look
Greetings
Andreas