How to create a pdf file from encoded string content - Codeigniter - php

I am getting response from cURL which is an encoded string format of pdf(i guess) - see attached image.
I am getting pdf file if i directly put the url in browser. Since its asking for api credentials for viewing the pdf, its not user friendly and i am looking for another way to directly download the file.
So i am trying to get the string content of the pdf file with cURL and i am getting exactly what in the image attached(only small portion attached).
Using that string content, i tried to save it as a plain txt file and from there i tried to decode the string text and to create a pdf file newly. After creating i need to download the same.
I could create text file with the string data i got from cURL and could create pdf also. But the downloaded file showing Failed to load PDF document.
Below is the code i have tried and i am not sure whether i tried correctly or not.
function pdf_download(){
$this->load->helper('file');
$curl = $this->api_call->callapi('GET',APIURL."carts/96171/tickets");
$content = $curl;
$my_file = FCPATH . '/document/text.txt';
if (write_file($my_file, $content) == FALSE)
{
echo 'Unable to write the file';
}
else
{
echo 'File written!';
}
$pdf_base64 = $my_file;
//Get File content from txt file
$pdf_base64_handler = fopen($pdf_base64,'r');
$pdf_content = fread ($pdf_base64_handler,filesize($pdf_base64));
fclose ($pdf_base64_handler);
//Decode pdf content
$pdf_decoded = base64_decode ($pdf_content);
//Write data back to pdf file
$pdf_file=FCPATH . '/document/ticket.pdf';
$pdf = fopen ($pdf_file,'w');
fwrite ($pdf,$pdf_decoded);//Creating a pdf from the encoded content in txt file
fclose ($pdf);
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=tickets.pdf");
ob_clean(); flush();
readfile($pdf_file);//downloading the pdf file
exit();
}

Since streaming a download to the browser requires sending headers, you must not output anything before sending headers. Therefore, you must get rid of:
if (write_file($my_file, $content) == FALSE)
{
echo 'Unable to write the file';
}
else
{
echo 'File written!';
}
If you definitely need to check if the file was written (for debugging purposes, I assume) you may use CI's log_message() to write a debug entry in the logs or just set a control variable. For example:
if (write_file($my_file, $content) == FALSE)
{
log_message('debug', "Unable to write file");
$file_written = false;
}
else
{
log_message('debug', "File succesfully written");
$file_written = true;
}
Also, there's some headers missing to ensure the file is not streamed to the browser but sent for download, as well as some required to make sure the file is correctly downloaded
header('Content-Description: File Transfer');
header('Content-Type: '. mime_content_type($pdf_file)); // since you're using Codeigniter, this will try to use the correct mimetype
header('Content-Disposition: attachment; filename="ticket.pdf"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($pdf_file));
readfile($pdf_file);

The wrong line in the above given code is $pdf_decoded = base64_decode ($pdf_content);.
It should be changed to $pdf_decoded = $pdf_content;
Since string in encoded format is already getting which is needed for creating PDF. So no need to decode it.
Also the above code is reduced as below.
function pdf_download(){
$this->load->helper('file');
$this->load->helper('download');
$cart_id=$this->input->get('cart_id');
$curl = $this->api_call->callapi('GET',APIURL."cart/'.$cart_id.'/tickets");
$pdf_file=FCPATH . 'document\voucher-'.$cart_id.'.pdf';
if (write_file($pdf_file, $curl))
{
force_download($pdf_file, NULL);
}
}

Related

Download differnt type of files using the same code PHP

I am trying to download files from server and it works fine for pdf files, I am wondering is there a way to download any type of files such as doc, zip,.. etc.
My code:
<?php
$doc = $sqlite->readDoc($documentId);
if ($doc != null) {
header("Content-Type:" . $doc['mime_type']);
header('Content-disposition: attachment; filename="something"');
print $doc['doc'];
} else {
echo 'Error occured while downloading the file';
}
?>
You'll want to identify the file - maybe using this function:
http://php.net/manual/en/function.mime-content-type.php
and then you can create a switch to indicate the content-type and appropriate disposition. There's a decent example here: PHP - send file to user
A simple function that can be used to download any file formate form path.
function DownloadFile($strFilePath)
{
$strContents = file_get_contents(realpath($strFilePath));
if (strpos($strFilePath,"\\") > -1 )
$strFileName = substr($strFilePath,strrpos($strFilePath,"\\")+1);
else
$strFileName = substr($strFilePath,strrpos($strFilePath,"/")+1);
header('Content-Type: application/octet-stream');
header("Content-Disposition: attachment; filename=\"${strFileName}\"");
echo $strContents;
}
Usage Example
$file = $_GET['file_id'];
$path = "../uploads/".$file; // change the path to fit your websites document structure
DownloadFile($path);

PHP-How to solve that Html Page Source is appending to the download file

I am downloading a file from Ftp folder after upload.
Problem is when i open the txt file it show s html page source appending with file content
If i preview image file(jpg or jpeg) it shows image is corrupted
If i open pdf error: Failed to load Pdf document
Please let me know where i am wrong.
Here is my code:
if (isset($_GET['id']) && basename($_GET['id']) == $_GET['id']) {
$filename = $_GET['id'];
} else {
$filename =NULL ;
}
$err = 'Sorry, the file you are requesting is unavailable.';
if (!$filename) {
// if variable $filename is NULL or false display the message
echo $err;
} else {
// define the path to your download folder plus assign the file name
$path = '/home/devestctrl/public_html/wp-content/uploads/'.$filename;
// check that file exists and is readable
if (file_exists($path) && is_readable($path)) {
// get the file size and send the http headers
$size = filesize($path);
header('Content-Type: application/octet-stream');
header('Content-Type: '.$mime);
header('Content-Length: '.$size);
header('Content-Disposition: attachment; filename='.$filename);
header('Content-Transfer-Encoding: binary');
// open the file in binary read-only mode
// display the error messages if the file canĀ“t be opened
$file = # fopen($path, 'rb');
if ($file) {
// stream the file and exit the script when complete
fpassthru($file);
exit();
} else {
echo $err;
}
} else {
echo $err;
}
}
I checked by using echo of $filename;
It shows the output in the file instead of printing in page.
error displays:
Sorry, the file you are requesting is unavailable.
After error also i can download, but echoed $filename displayed in file.
Insert into table:
echo "<tr><a href='?id=" . $row["FileupName"]. "'>".$row["FileupName"]."</td></tr>";
You cannot output data to a page and download a file at the same time. One request from your browser will let you do one response. This response is normally displayed in the browser as a page, unless you set the download headers, then the browser will ask you to download the response to a file.
So what you'll need to do is have two requests and responses: In the first, you output your page and a link the user needs to click (or JavaScript or a refresh meta tag to do it automatically) to download the file in a second request.

Download a file with php and polymer

I'm having some trouble with this one. I have found some helpful scripts on the web and have been modifying them for my needs. However, I can't seem to download a file. It will respond back with the contents of the file but doesn't download it. I am using Polymer 1.0+ for my client side and PHP for my server side. The client side code to download a file is as follows:
<!--THIS IS THE HTML SIDE-->
<iron-ajax
id="ajaxDownloadItem"
url="../../../dropFilesBackend/index.php/main/DownloadItem"
method="GET"
handle-as="document"
last-response="{{downloadResponse}}"
on-response="ajaxDownloadItemResponse">
</iron-ajax>
//THIS IS THE JAVASCRIPT THAT WILL CALL THE "iron-ajax" ELEMENT
downloadItem:function(e){
this.$.ajaxDownloadItem.params = {"FILENAME":this.selectedItem.FILENAME,
"PATH":this.folder};
this.$.ajaxDownloadItem.generateRequest();
},
The server side code is as follows (the url is different because I do some url modification to get to the correct script):
function actionDownloadItem(){
valRequestMethodGet();
$username = $_SESSION['USERNAME'];
if(validateLoggedIn($username)){
$itemName = arrayGet($_GET,"FILENAME");
$path = arrayGet($_GET,"PATH");
$username = $_SESSION['USERNAME'];
$downloadItem = CoreFilePath();
$downloadItem .= "/".$_SESSION['USERNAME']."".$path."".$itemName;
DownloadFile($downloadItem);
}
else {
echo "Not Logged In.";
}
}
function DownloadFile($filePath) {
//ignore_user_abort(true);
set_time_limit(0); // disable the time limit for this script
//touch($filePath);
//chmod($filePath, 0775);
if ($fd = fopen($filePath, "r")) {
$fsize = filesize($filePath);//this returns 12
$path_parts = pathinfo($filePath);//basename = textfile.txt
$ext = strtolower($path_parts["extension"]);//this returns txt
$header = headerMimeType($ext); //this returns text/plain
header('Content-disposition: attachment; filename="'.$path_parts["basename"].'"'); // use 'attachment' to force a file download
header("Content-type: $header");
header("Content-length: $fsize");
header("Cache-control: private"); //use this to open files directly
while(!feof($fd)) {
$buffer = fread($fd, 2048);
echo $buffer;
}
}
fclose ($fd);
}
Any help on this one would be greatly appreciated.
First you will need the file handle
$pathToSave = '/home/something/something.txt';
$writeHandle = fopen($pathToSave, 'wb');
Then, while you are reading the download, write to the file instead of echoing
fwrite($writeHandle, fread($fd, 2048));
Finally, after writing to the file finished close the handle
fclose($writeHandle);
I neglect the error check, you should implement your own.

Saving pdf to BLOB (in mssql server) and output it back on website (php)

I need to save a pdf file into BLOB (database is MsSql 2012, but I would need it work on 2008 too).
Here is compilation of what I have tried so far:
(File where I save pdf into database)
function preparePDF2String($filepath)
{
$handle = #fopen($filepath, 'rb');
if ($handle)
{
$content = #fread($handle, filesize($filepath));
$content = bin2hex($content);
#fclose($handle);
return "0x".$content;
}
}
$out = preparePDF2String('pdf/pdf.pdf');
$q_blob = "INSERT INTO HISTORIA_ARCHIWUM_test(PDFName, PDFData) VALUES('First test pdf', $out) ";
$r_blob = mssql_query($q_blob,$polacz);
Results (ok, I think)
(Now the php file where I try to output the pdf)
// header('Content-type: application/pdf');
// readfile('pdf/pdf.pdf'); - this works just fine, so pdf is ok
$q_blob = "select top 1 * from HISTORIA_ARCHIWUM_test";
$r_blob = mssql_query($q_blob,$polacz);
$w_blob = mssql_fetch_array($r_blob);
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="the.pdf"');
echo $w_blob['PDFData'];
//echo hex2bin ($w_blob['PDFData']); - I also tried this - same problem
Problem: when I try to output the pdf in the browser I get error (this pdf is of not supported format). It won't open in Adobe reader also. My guess is that I output it wrong, but maybe it is the way I save it?
EDIT from comments
It seems php+mssql truncates string when you get it from db, but its manageable in php.ini. I set mssql.textlimit = 160000 and mssql.textsize = 160000 and it works fine with Hex conversion and varchar(max).
You are transforming the pdf data before you save it to the database, you have to undo the transformation before you output it.
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="the.pdf"');
echo hex2bin(substr($w_blob['PDFData'], 2));
Also why are you transforming the data in the first place, just save it as binary.

microsoft tag download barcode to disk

I am using microsoft tag php library by Scott Vanderbeck.
It has a function to output the barcode to browser as an image to browser, but I would like download and save to disk. My goal is to loop through all the tags and download each barcode as an image onto a disk. I am not sure how to accomplish this.
Here is my code
require_once('MSTag_v2.php');
$MSTagAuthToken = "your token";
//Create an MSTag interface instance
$msTag = new MSTag();
//Create User Credentials
$userCredential = new UserCredential($MSTagAuthToken);
//Display Microsoft Tag image in browser
$result = $msTag->GetBarcode($userCredential,'MAIN','Cyclamen coum Pewter','jpeg',1);
if($result)
{
ob_start();
$length = strlen($result);
header('Last-Modified: '.date('r'));
header('Accept-Ranges: bytes');
header('Content-Length: '.$length);
header('Content-Type: image/jpeg');
print($result);
ob_end_flush();
exit;
}
else
{
echo $msTag->getLastException();
}
You could save the images directly to disk
if($result)
{
file_put_contents($filename, $result);
}
Just generate a filename for each so you do not overwrite them (maybe use tempnam()).

Categories