File only downloading when opened in new window/tab - php

I have a function that creates different file types depending on a variable, I have it generating an XML, but when I click the link to the page to do so (XML), nothing happens. If I click to open it in a new tab or manually enter the url in the title bar then the file will download as I want it to.
function asset($asset_id, $display = ''){
$this->load->model('model_asset');
$asset = $this->model_asset->get_by_id($asset_id, true);
switch($display) {
case 'xml':
$this->load->helper('array_to_xml_helper');
$asset_arr = get_object_vars($asset);
$filename = $asset->title .'-'. $asset->subtitle . '.xml';
$xml = Array2XML::createXML('asset', $asset_arr);
header ("Content-Type:text/xml");
header('Content-Disposition: attachment; filename="'. $filename .'"');
echo $xml->saveXML();
break;
}
}
How can I make this work with dynamically generated files (I'm using a arraytoxml utility function I found here)

You can try to set file in attachement
Add this to your headers :
Content-disposition: attachment
filename=huge_document.pdf

Related

PHP download doesn't work properly

I just wanted to make some kind of "download service" but it isn't working.
Whole download.php:
<?php
include "utils/config.php";
include "utils/utils.php";
if($isLoggedIn && isset($_POST['id']) && hasProduct($userid,$_POST['id'])){
$ID = $_POST['id'];
$pdata = getProduct($ID);
$file = $pdata['file'];
$name = $pdata['dlfile'];
$mime = $pdata['file_mime_type'];
#echo $file."<br>".$name."<br>".$mime;
/**
* $file = "assets/files/151708025047541"
* $name = "API.jar"
* $mime = "application/java-archive"
*/
download($file,$name,$mime); // <-- wouldn't work
#download("assets/files/151708025047541","API.jar","application/java-archive"); // <-- wouldn't work
}
#download("assets/files/151708025047541","API.jar","application/java-archive"); // <-- would work fine
?>
Function "download" in utils.php:
function download($f_location, $f_name, $type){
header('Content-Description: File Transfer');
header('Content-Type: '.$type);
header('Content-Length: ' . filesize($f_location));
header('Content-Disposition: attachment; filename="' . basename($f_name).'"');
ob_clean();
readfile($f_location);
}
The only thing "config.php" contains are some variables.
The only thing "utils.php" contains are some functions and it's connecting to the database (which is needed for $isLoggedIn, hasProduct (...) and getProduct (...).
The download itself is wokring, but it wants to download a file with zero content and with the name "download.php".
At my comments you see, if I try the same function (with static args) outside the if-block the download works fine. But if I try to use function (with static args) inside the if-block it will give me the same problem.
Funny thing is that the same function still worked a few months ago.
Am I doing something wrong? How can I download these files dynamic with an authorization-check (as I have already tried)?
I hope you understand my problem:)
A Download-Manager add-on was trying to catch the download..
Just added an exception/disabled the add-on and now it's working!

File is downloading without extension?

I am trying to download a PDF file but when i click on the download button it downloads the file without extension. That is there is no PDF extension with the file when i download it!
Action:
public function executeDownload(sfWebRequest $request) {
$this->ebook_id = $request->getParameter('ebook', $this->default_ebook);
$this->ebook = $this->ebooks[$this->ebook_id];
if (!is_array($this->ebook))
return;
// Allow user to download the ebook (and make sure there is no other output)
$this->setLayout(false);
sfConfig::set('sf_web_debug', false);
$content = sfConfig::get('sf_root_dir').'/web'.$this->ebook['ebook'];
//echo "<p>PDF: $content</p>"; var_export(filesize($content));exit;
// Check if the file exists
$this->forward404Unless(file_exists($content));
// Record the download for this eBook
$c = new Criteria();
$c->add(EbookDownloadsPeer::EBOOK_SLUG, $this->ebook_id);
$ebook = EbookDownloadsPeer::doSelectOne($c);
$ebook->setLastDownloaded(time());
$ebook->setEbookDownloads($ebook->getEbookDownloads()+1);
$ebook->save();
// Adding the file to the Response object
$content_type = (in_array($this->ebook_id, array('readyourbody', 'whyamifatigued', 'nutrientsfromfood'))) ? 'application/pdf': 'image/jpeg';
$this->getResponse()->clearHttpHeaders();
$this->getResponse()->setHttpHeader('Pragma: public', true);
$this->getResponse()->setContentType($content_type);
$this->getResponse()->setHttpHeader('Content-Disposition', 'attachment; filename="'.$this->ebook['name'].'"');
$this->getResponse()->setHttpHeader('Content-Length', filesize($content));
$this->getResponse()->sendHttpHeaders();
$this->getResponse()->setContent(readfile($content));
return sfView::NONE;
}
Template:
<div class="cyan3 txt-large txt-c">
<?php echo link_to('Click here','ebooks/download?ebook='.$ebook_id,'') ?> to <?php echo link_to('download it now','ebooks/download?ebook='.$ebook_id,'') ?>!
</div><br />
</div>
Check the contents of the $this->ebook array and look for a field that holds the file extension. Add this value to the line
$this->getResponse()->setHttpHeader('Content-Disposition', 'attachment; filename="'.$this->ebook['name'] . '"');
so it because something like
$this->getResponse()->setHttpHeader('Content-Disposition', 'attachment; filename="'.$this->ebook['name'] . $this->ebook['extension'].'"');
Please append .pdf as extension to your ebook name.
It will work.

Downloading excel file from controller in code igniter

I am having the following issue:
I am using code igniter as php framework, and from one of my views I do an ajax call to a function that generates and xlsx file using PHPExcel and data from mysql database. The file is correctly created in the server but when I try to force_download it won't download anything. Here is the php function:
public function generar_excel($idCotizacion){
isLogged($this->session->userdata('logged_in'));
isAdmin($this->session->userdata('logged_in'));
$cotizacion = $this->cotizacion_model->get_cotizacion_by_id($idCotizacion);
$propuestas = $this->propuesta_model->getPropuestasPorCotizacion($idCotizacion);
error_reporting(E_ALL);
date_default_timezone_set('Europe/London');
require_once 'application/libraries/PHPExcel-1.8/Classes/PHPExcel/IOFactory.php';
require_once 'application/libraries/PHPExcel-1.8/Classes/PHPExcel.php';
$excel2 = PHPExcel_IOFactory::createReader('Excel2007');
$excel2 = $excel2->load('prueba.xlsx'); // Empty Sheet
$excel2->setActiveSheetIndex(0);
$excel2->getActiveSheet()->setCellValue('C8', $cotizacion["capitas"])
->setCellValue('C2', $cotizacion["empresa_nombre"])
->setCellValue('C9', $cotizacion["masa_salarial"])
->setCellValue('B11', $cotizacion["aseguradora_actual"])
->setCellValue('B13', $cotizacion["variable"]/100)
->setCellValue('B14', '0.6')
->setCellValue('B12', '0');
$letra = 'C';
foreach($propuestas->result_array() as $row) {
$excel2->getActiveSheet()->setCellValue($letra.'11', $row["nombre"])
->setCellValue($letra.'13', $row["variable"]/100)
->setCellValue($letra.'14', '0.6')
->setCellValue($letra.'12', '0')
->setCellValue($letra.'16', '=C$8*'.$letra.'12+C$9*'.$letra.'13+C$8*'.$letra.'14')
->setCellValue($letra.'17','=(B$16-'.$letra.'16)*13')
->setCellValue($letra.'18','=1-('.$letra.'16/B16)');
++$letra;
}
$objWriter = PHPExcel_IOFactory::createWriter($excel2, 'Excel2007');
$nombreArchivo = 'CuadroComparativo-'.$cotizacion["empresa_nombre"].'.xlsx';
$objWriter->save('uploads/'.$nombreArchivo);
$fileContents = file_get_contents('http://rpm.singleton.com.ar/uploads/'.$nombreArchivo);
//print_r($fileContents);
$this->load->helper('download');
force_download($nombreArchivo, $fileContents);
}
The response and preview from inspecting the browser are unreadable.
Thank you!
Set the MIME type for the data you're sending in the force_download() function. The browser may be either trying to best guess it, or just outputting exactly what you send it (which may be the 'unreadable' data you're referring to).
Try changing your force_download line to:
force_download($nombreArchivo, $fileContents, TRUE);
This will set the MIME type based on your file extension (xlsx), with should force the browser to download the file.
I solved it by adding in the success function of ajax the following:
success: function(json) {
var content = JSON.parse(json);
//alert(content);
if (content.error) {
$('#error').html(content.response);
$('#error').show();
$('#success').hide();
} else {
// alert(content);
location.href="http://rpm.singleton.com.ar/uploads/"+content.response;
//location.href = "<?php echo site_url('administrador'); ?>/" + content.response;
}
},
And in the php i echo the file name.
Try this code:
header('Content-Type: application/vnd.ms-excel');
header("Content-Disposition: attachment; filename={$nombreArchivo}.xls");
$this -> load -> view ('view_file',$fileContents);

PHP "save dialog" for file received from web service

I'm using WSO2 WS Framework and I managed to run example in which web service returns an image as a MTOM attachment which is then saved by the client using file_put_contents(...) command.
Service:
<?php
function sendAttachment($msg){
$responsePayloadString = <<<XML
<ns1:download xmlns:ns1="http://wso2.org/wsfphp/samples/mtom">
<ns1:fileName>test.jpg</ns1:fileName>
<ns1:image xmlmime:contentType="image/jpeg" xmlns:xmlmime="http://www.w3.org/2004/06/xmlmime">
<xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:myid1"></xop:Include>
</ns1:image>
</ns1:download>
XML;
$f = file_get_contents("test.jpg");
$responseMessage = new WSMessage($responsePayloadString,
array( "attachments" => array("myid1" => $f)));
return $responseMessage;
}
$operations = array("download" => "sendAttachment");
$service = new WSService(array("operations" => $operations, "useMTOM" => TRUE));
$service->reply();
?>
Client:
<?php
$requestPayloadString = '<download></download>';
try {
$client = new WSClient(
array( "to" => "http://SPLINTER/MTOM/service.php",
"useMTOM" => TRUE,
"responseXOP" => TRUE));
$requestMessage = new WSMessage($requestPayloadString);
$responseMessage = $client->request($requestMessage);
printf("Response = %s \n", $responseMessage->str);
$cid2stringMap = $responseMessage->attachments;
$cid2contentMap = $responseMessage->cid2contentType;
$imageName;
if($cid2stringMap && $cid2contentMap){
foreach($cid2stringMap as $i=>$value){
$f = $cid2stringMap[$i];
$contentType = $cid2contentMap[$i];
if(strcmp($contentType,"image/jpeg") ==0){
$imageName = $i."."."jpg";
if(stristr(PHP_OS, 'WIN')) {
file_put_contents($imageName, $f);
}else{
file_put_contents("/tmp/".$imageName, $f);
}
}
}
}else{
printf("attachments not received ");
}
} catch (Exception $e) {
if ($e instanceof WSFault) {
printf("Soap Fault: %s\n", $e->Reason);
} else {
printf("Message = %s\n",$e->getMessage());
}
}
?>
Instead of that I would like to open a "Save dialog" to choose between opening or saving the file. When searching for solution I read about setting heders like:
header('Content-type: application/octet-stream');
header('Content-disposition: attachment; filename="test.jpg"');
But it didn't work well. "Save dialog" poped up, but when image couldn't be opened saying that file is empty.
Actually I don't understand very good how this MTOM attachments thing is working. In client code, I think $f is a string and when I do printf($f) it prints 0(zero) so how can I save this string as an image?
If you want to use that headers, you have to output the file content, not save it somewhere.
header('Content-type: application/octet-stream');
header('Content-disposition: attachment; filename="test.jpg"');
// Output file. This must be the ONLY output of the whole script
echo $rawFileContents;
The basics is that at the moment you have your whole file content loaded in a variable (and it seems is $f in your code), you output it instead of write it in a file (as I think you're doing now). So, the three lines of code I gave you should replace the file_put_contents() calls.
Instead, if you want to save the file in your /tmp folder, ok, do it, but then use instead
header('Location: /tmp/' . $imageName);
This way you redirect the user browser directly to the saved file, and let users do what they want with it.

PHP: open a file download dialog [duplicate]

This question already has answers here:
Force file download with php using header()
(7 answers)
Closed 9 years ago.
I have an MPEG file (.mpg) hosted in Amazon S3, that I want to link to a page I have, so the user will be able to download it from the page.
I have in my page a link:
bla bla"
The link to the file works when I right-click it and choose "Save Target As" , but I would like it to work also when I left click it, and that it will open a file download dialog. right now, a left click will direct to a page that has the video directly played in it (in FireFox) or just won't load (in Internet Explorer).
I am working in PHP, why does this happen?
You probably want to wrap the file within a "download" PHP script that sends the appropriate Content-Disposition header telling the browser to treat it as a download instead of a content item.
For instance:
header("Content-Disposition: attachment; filename=yourfilenamehere.ext>");
http://support.microsoft.com/kb/260519
This will work with UTF-8 filenames (say you have one in a variable called $orfilename):
function detectUserAgent() {
if (!array_key_exists('HTTP_USER_AGENT', $_SERVER))
return "Other";
$uas = $_SERVER['HTTP_USER_AGENT'];
if (preg_match("#Opera/#", $uas))
return "Opera";
if (preg_match("#Firefox/#", $uas))
return "Firefox";
if (preg_match("#Chrome/#", $uas))
return "Chrome";
if (preg_match("#MSIE ([0-9.]+);#", $uas, $matches)) {
if (((float)$matches[1]) >= 7.0)
return "IE";
}
return "Other";
}
/*
* We have 3 options:
* - For FF and Opera, which support RFC 2231, use that format.
* - For IE and Chrome, use attwithfnrawpctenclong
* (http://greenbytes.de/tech/tc2231/#attwithfnrawpctenclong)
* - For the others, convert to ISO-8859-1, if possible
*/
$formatRFC2231 = 'Content-Disposition: attachment; filename*=UTF-8\'\'%s';
$formatDef = 'Content-Disposition: attachment; filename="%s"';
switch (detectUserAgent()) {
case "Opera":
case "Firefox":
$orfilename = rawurlencode($orfilename);
$format = $formatRFC2231;
break;
case "IE":
case "Chrome":
$orfilename = rawurlencode($orfilename);
$format = $formatDef;
break;
default:
if (function_exists('iconv'))
$orfilename =
#iconv("UTF-8", "ISO-8859-1//TRANSLIT", $orfilename);
$format = $formatDef;
}
header(sprintf($format, $orfilename));
On download page do the following
$filename = $_GET['movie']; //Get the filename
if(is_file($filename)) {
//If you want to read and output the contents do it here
header('Content-disposition: attachment; filename='.$filename);
}
exit();
This will tell the browser to treat this as an attachment, thus forcing a download box.

Categories