In our app, we direct the user to download a .mobileconfig. Originally the problem was Safari just displayed the XML rather than downloaded that, but we got around this with a PHP script (below).
<?php
$file = "http://example.com/myProfile.mobileconfig";
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=\"$file\"");
readfile ($file);
?>
However we commonly see it where the .mobileconfig is downloaded and automatically it brings up the 'do you wish to install page'. How is that done? Are we missing something in Content-Type?
Thanks,
Sam
Experienced same problem, the solution is below.
Just set the content type, works like a charm ;)
public function controllerMethod() {
// $config contains generated XML file as string.
$config = $this->generateConfig('apple', Input::all());
// Make response -> attach $config to response
$response = Response::make($config);
// Set headers
$response->headers->set('Content-Type', 'application/x-apple-aspen-config');
$response->headers->set('Content-Disposition', "attachment; filename='mail.mobileconfig'");
return $response;
}
Related
I am saving a pdf file, and then attempting to download it using php.
The script seemed to work fine, but all of the sudden not anymore.
Can anybody see what I am missing?
PS: the file I am downloading is only 4.3kb big, so I assume that would be because it is not downloading at all. The actual file size should be bigger than this.
$pdf->output(ROOTDIR.'/modules/addons/statement_generator/reports/statement.pdf');
if($action=='print'){
$file_name = 'statement.pdf';
$file_url = "http://".$_SERVER['SERVER_NAME']."/modules/addons/statement_generator/reports/" . $file_name;
header('Content-Type: application/pdf');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"".$file_name."\"");
readfile($file_url);
exit;
}
The $pdf->output() call will already send the PDF to the client. The file will not be saved to your local folder (Didn't you checked at least this?) because you have to pass "F" as the snd parameter.
After that you try to read from an URL (!!!!) that does not exists and which maybe return a nicely styled 404 html response. Two issues here:
Why are you using http when you have the local path used some lines above? Use the local path only!
The content returned by the URL is append to the already send PDF which ends in a document mixed of PDF and HTML (the 404 response) -> corrupted PDF
Conclusion: Use "F" as the 2nd parameter and use the same path for both writing and reading and not a mix of local path and URL.
I am trying to let the user download a file in the Slim php framework.
The intended use is that the file will be:
http://api.test.com/item/123.json <- returns json string with data
http://api.test.com/item/123.pdf <- download pdf-file with human-readable presentation of data
I have the code producing the PDF, but what I need is to make Slim send the correct headers so the file will be downloaded.
This is the following code I have (working) for the existing system:
header("Pragma: public");
header('Content-disposition: attachment; filename='.$f->name);
header('Content-type: ' .$f->type);
header('Content-Transfer-Encoding: binary');
echo $f->data;
Following is my current (non-working) Slim-code where the headers I declare is not sent to the browser. Instead I get text/html. (Note that this example only contains one header, I have also tested to see if any other header manipulation would cause any effect, but it haven't). The switch-case of json/pdf/xml will be added later on.
R::setup();
$app = new \Slim\Slim();
$app->get('/item', function() use ($app) {
$f = R::load('file', 123);
$app->response->headers->set("Content-Type", "application/pdf"); //$f->type
$app->response->setBody($f->data);
});
$app->run();
The $app->response->setBody($f->data) however works fine.
Problem solved. Turned out to be a included php class with whitespace in it. This messed up the headers i guess.
Solved by creating a new, empty project and include step by step until the bad class showed.
Working solution for setting headers inside a Slim function;
<?php
require 'vendor/autoload.php';
$app = new \Slim\Slim();
$app->get('/foo', function () use ($app) {
$app->response->headers->set('Content-Type', "application/pdf");
$app->response->setBody("foo");
});
$app->run();
?>
Updated: This is the headers I use to let a user download a PDF:
$app->response->headers->set('Content-Type', $f->type);
$app->response->headers->set('Pragma', "public");
$app->response->headers->set('Content-disposition:', 'attachment; filename=' . $f->name);
$app->response->headers->set('Content-Transfer-Encoding', 'binary');
$app->response->headers->set('Content-Length', $f->size);
$app->response->setBody($f->data);
Hi I'm downloading a file to an app on iOS using the function readfile() on a PHP web service and I want to know if the file is downloaded correctly but I don't know how I can do that.
So what I'm trying is to do some echo to know if the file has been downloaded like this:
echo "before";
readfile($file);
echo "after";
But the response I get is this:
beforePK¿¿¿
Any one knows what does this mean or how can I know if the file is downloaded correctly?
UPDATE:
Yes it's a zip file, here are my headers
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$ticket");
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
You're trying to output the contents of a zip file aren't you?
readfile($file) works the same as echo file_get_contents($file). If you're trying to present someone a file to download, do not add any additional output else you risk breaking the file.
I would also recommend reading up on the header function. That way you can explicitly tell the browser that you're sending a file, not an HTML page that has file-like contents. (See the examples involving Content-Type)
PHP should be setting the correct headers prior to readfile() - this LITERALLY reads the file out to the browser/app... but the browser/app needs to know what to do with it...
Usually you just assume that once the connection has closed that the data is done being transferred. If you want to validate that the file has been transferred fully, and without corruption you'll need to use a data structure like XML or JSON which will:
Delimit the data fields and cause the XML/JSON parser to throw an error if one is omitted, aka the transfer was cut off before it finished.
Allow you to embed more than one piece of data with the response, eg. an MD5 hash of the file that can be re-calculated client-side to verify that the data is intact.
eg:
$file = 'myfile.zip';
$my_data = array(
'file' => base64_encode(file_get_contents($file)),
'hash' => md5_file($file)
)
//header calls
header(...)
echo json_encode($my_data);
exit;
I have a project that is composed of two separate parts. On one side, there is a Rails app and on the other side, there is an ExtJs client with CakePhp server.
What needs to happen is this: attach a file in Rails (this is done by using Paperclip) and be able to read them on the Cake side. It might be easy if both systems were on the same server, but this needs to be done remotely, so the Cake side will call a Rails route and Rails will provide the file.
Cake code to download file:
function download_file($path, $file_name, $content_type, $size) {
if ($fd = fopen ($path, "r")) {
header("Content-type: " . $content_type);
header("Content-Disposition: attachment; filename=\"".$file_name."\"");
header("Content-length: $size");
header("Cache-control: private"); //use this to open files directly
header('Pragma: public');
ob_clean();
flush();
echo readfile($path);
// $this->log(apache_response_headers(), 'debug');
}
fclose ($fd);
}
Ruby / Rails code to provide document:
send_file document.path, :type => document.document_content_type
Rails Document model:
class Document < ActiveRecord::Base
belongs_to :attachable, :polymorphic => true
has_attached_file :document,
:url => '/download/:id/:fingerprint/documents'
def path
document.path
end
end
Everything works as expected except one type of file, .docx. I can upload and after that download any other files except those of this type. I can read the file in rails, after it was uploaded, with no problem. There seems to be something wrong on the Cake side, as what happends there is this: I can download the file, but I can't open it with LibreOffice after that. I seems that the mime types are set up correctly as apache and the browser recognize the type of file and the application to open it. It seems I can open the file with TextEdit.
So, the question is: what is wrong? Why don't .docx files open on the php / Cakephp side?
Any ideas will be highly appreciated.
Found the answer for this. Actually it was some sort of Cake issue after all, and it was related to the way Cake is rendering views.
Cakes MediaView doesn't allow working with remote files because of the way it builds the path of the file, but I've added
$this->autoRender = false;
and everything went well after that.
This post was helpful: Corrupted .docx download using phpdocx
Thanks to burzum as well for the hint with MediaView.
I have uploaded some sample mp3 files to a directory outside of httpdocs, I have ensured that this is accessible to PHP by configuring open_basedir correctly and tested that this directory is working.
What I would like to do is stream these files via a PHP file as non-authenticated users should never have access to these files. I am currently using jPlayer and expect the setMedia function should look similar to this:
$("#jquery_jplayer").jPlayer("setMedia", { mp3: "stream.php?track=" + id + ".mp3" });
I have tried setting content headers etc in stream.php and it currently looks like this:
$filePath = "../song_files/mp3/";
$fileName = "$_GET[track].mp3";
header("Content-Type: audio/mpeg");
header('Content-Disposition: attachment; filename="'.$fileName.'"');
getFile($filePath + $fileName);
If I load this page directly, the mp3 file downloads and plays fine, but when I use the above javascript, jPlayer doesn't play the track.
I have had a look at this post ( Streaming an MP3 on stdout to Jplayer using PHP ) and it appears the user was trying to achieve exactly what I want, but upon testing the solution I keep running into a problem, all I get is "CURL Failed".
Are there any different methods I can use to achieve this. Pointing me in the right direction would be greatly appreciated.
After searching around some more I have found a solution that is working fine. I used the code from a similar topic ( PHP to protect PDF and DOC )
I will place the code I used here to help answer the question correctly:
//check users is loged in and valid for download if not redirect them out
// YOU NEED TO ADD CODE HERE FOR THAT CHECK
// array of support file types for download script and there mimetype
$mimeTypes = array(
'doc' => 'application/msword',
'pdf' => 'application/pdf',
);
// set the file here (best of using a $_GET[])
$file = "../documents/file.doc";
// gets the extension of the file to be loaded for searching array above
$ext = explode('.', $file);
$ext = end($ext);
// gets the file name to send to the browser to force download of file
$fileName = explode("/", $file);
$fileName = end($fileName);
// opens the file for reading and sends headers to browser
$fp = fopen($file,"r") ;
header("Content-Type: ".$mimeTypes[$ext]);
header('Content-Disposition: attachment; filename="'.$fileName.'"');
// reads file and send the raw code to browser
while (! feof($fp)) {
$buff = fread($fp,4096);
echo $buff;
}
// closes file after whe have finished reading it
fclose($fp);
</code></pre>