Can't download files. Garbage code displays - php

I have Drupal website and my users can no longer download files. (docx, xlsx, etc). In firefox only, when the user clicks a link to download a file the page displays garbage code.
I read elsewhere the solution is to add the following, but it didn't work. Instead, the user is prompted with a dummy download for the application type each time the page reloads.
drupal_set_header('Content-type: application/octet-stream; charset=utf-8');
I have a simple module which has a page that spits out the links to the files. In this module I added the above to the hook_init() function.
I've never encountered this problem before, and I'm not sure why it started. Any help would of course be greatly appreciated. If I find a solution before someone replies with the answer I'll post it here for future reference.

Give this a roll for your MIME:
drupal_set_header('Content-type: application/force-download');

This happens because MIME types are not set correctly.
You can either force Drupal to set the content-type header to appropriate MIME type, or set it at the server side.
I'd recommend you to do it in the .htaccess file in your files folder (sites/default/files by default)
Just put the below code in the .htaccess file (or you can create a new .htaccess file if it's not there).
AddType application/octet-stream .doc .xls .pdf
Note that hook_init() gets fired at every normal page request. Never do this in this hook or you will end up facing many problems.

Related

Uploading and displaying .html files in browser

I'm working on a little project with a few friends, and have set up a pretty simple PHP upload script that only certain users can access. I am not worried about any type of attacks against the server, since this is for fun, but I do have a question.
I've made a subdomain (static.foo.bar) where the uploaded files are moved to. This subdomain had mod_php turned off, to prevent malicious upload and execution of php scripts. The script also checks for file extensions and mime content types, but I assume those can easily be bypassed/spoofed.
However, a user could easily upload an .html file and have it redirect somewhere else. Likewise, they could upload an image file instead and have it display an image in the browser, instead of being asked to download the image.
I assume this is the behavior of the browser, but I've also noticed that when uploading a file to sendspace (or any other service), even if the file is .html (and valid html) it will ask the user to download it instead of displaying it on the website.
I am running Apache on CentOS.
How do I accomplish this?
ForceType is probably what you're looking for.
# In your .htaccess file
<Location /uploads_directory>
ForceType application/octet-stream
</Location>
You want to set all files' mime type to application/octet-stream so the browser will download them instead of trying to show the content.

Download KML File Instead of View in Browser

I am working on a project which creates a KML File (just like an XML file, but used for Google Earth). Whats interesting is when I link to the newly created file, on my local machine, running XAMPP, the file is downloaded automatically, however when I move it to my web server (Linux, Fedora 8 on EC2) the link just loads the KML file in the browser as if it was an HTML file.
How can I force it to download the file instead of viewing it in the browser?
Here's how to link is displayed with PHP,
echo "<a href='$currentTime.kml'><img heigth=\"15px\" width=\"13px\" src=\"images/KML_Icon.gif\" /> Download</a>";
Any advice would help, thanks!
What you need to do is to specify the headers so the Browser knows what to do with the information that you are sending. So before you send anything to the browser you will need to specify the headers.
If you are linking to a specific file, then you will have to create a little "download manager" that will do this for you.
<?
header('Content-disposition: attachment; filename=the-name-you-want-them-to-see-in-their-download.pdf');
header('Content-type: text/xml'); //Since KML files are based on XML this is probably the best Content type to send to the user.
readfile('the-file-you-want-to-present')
?>
That should do it.
Thank you for your guys' input, but Oded had the answer regarding the mime types.
On the server there's a file called mime.types which didn't contain the mime type for a KML file, I added in
application/vnd.google-earth.kml+xml
And it now downloads the file instead of loading it in the browser, by the way apache needs to be restarted once you have made the changes.
I had this a long while ago, I used a method similar to this:
http://webdesign.about.com/od/php/ht/force_download.htm

.htaccess Configuration for .SSA Files

I have a web app which performs a character encoding conversion on .ssa files (SubStation Alpha - subtitle files basically). The MIME type of these files is text/plain. When the app performs the conversion it creates a link to download the new file. In Safari this works perfectly. However in Chrome when you click the download link it attempts to save the file as download.txt no matter what the actual filename is. In Firefox (beta) it tries to save it as something like kP3844h1.txt.part. How can I tell these browsers just to use the filename that is linked? In all cases the contents of the file is correct, it's just the name in the browser's "Save As..." dialog that gets screwed up.
Currently my .htaccess looks like:
AddType text/plain ssa
<Files *.ssa>
#ForceType application/octet-stream
Header set Content-Disposition attachment
</Files>
I've tried with both of the <Files> lines uncommented, and with either one commented on its own, but none of those options gives me the solution I'm looking for.
Also, the app is written in PHP, so if there's something I could be doing in the PHP code instead of messing with the .htaccess, I'm open to suggestions.
Use Content-Disposition attachment; filename="$actual_filename.txt" as header. Replace $actual_filename.txt by the actual name of the file. I have no idea if this is possible in the Apache configuration, but if you pipe the files through PHP, you might be able to set the header with the header function.

How to use google docs viewer for embedding ppt files on a webpage, if the file is served by a php script?

I've uploaded an MS powerpoint file to my server, and I'm trying to use Google Docs viewer (http://docs.google.com/viewer) to display it on a webpage.
The file is available here:
http://elgg.wamped.org/test.ppt
If I invoke the docs viewer with the above URL, it is working as expected, see:
http://docs.google.com/viewer?url=http%3A%2F%2Felgg.wamped.org%2Ftest.ppt
But when I'm trying to serve the same file through a very simple php script to the viewer, it fails rendering with the not too helpful error message: "Sorry, we are unable to generate a view of the document at this time", see:
http://docs.google.com/viewer?url=http%3A%2F%2Felgg.wamped.org%2Freadfile.php
The script that serves the file is as follows:
<?php
header('Content-type: application/vnd.ms-powerpoint');
header('Content-Disposition: attachment; filename="test.ppt"');
readfile('test.ppt');
?>
I've tried playing around with various header fields like Pragma and Cache-Control, but nothing helped. I also tried slicing the output file and echoing in chunks, that also did not do any good. Checked the apache log on the server, checked the response headers, everything seems fine to me.
Any ideas what am I doing wrong here?
EDIT: Although I haven't found a solution to this issue, I stumbled upon a site that does the same (or seems to do more than that, actually) as Google Docs Viewer. http://embedit.in has support for a wide range of file types, has an API, and does the job nicely, so I'll just probably go with that one. However, out of curiousity, I'd still like to know what is wrong with the piece of code below. So any suggestions are more than welcome.
Have you tried naming the php file with a .ppt file extension instead of .php? Whether or not your server will process php code in a file that doesn't have a .php file extension is another problem. But Google Docs may simply say NO to loading any file with a .php extension on it.
Capitalize the T in Content-Type. I also provided the Content-Length header. My filehandler works now.
It looks like you might be missing some headers. You might also want to see if the file is in the same directory as readfile.php, because google might store each file on a remote server.

Logging dynamically served files in APACHE

I'm serving up Zip and PDF files on the fly via PHP using an output such as:
header('Content-Disposition: attachment; filename="'.$project->name .'.zip"');
echo($zipfile->zl_pack());
I can't find any reference to these downloads in my APACHE logs though. Is it not logged due to being dynamic?
Do I need to actually write the file to the webserver and then serve the result up to get it logged or am I missing something?
Cheers,
Niggles
Correct. httpd does not look at outgoing headers for logging. error_log() will send a message to httpd's error log, but there's no way to put something in the access log.
The request to the PHP program that generates that header should be logged. The filename mentioned in the content disposition header won't be.
I believe mod_perl would allow you to add custom logging, I don't know if mod_php provides a similar feature.
As a workaround you could use mod_rewrite to have the *.zip file logged and still served it through PHP without actually writing it to the filesystem, the client will have to send two requests though.
1) Change your current script so that it doesn't produce the file, but instead puts the parameters needed for the file creation in the session; instead of the current header and file content you would put header('Location: '.$project->name .'.zip');
2) This would cause the second request. Since the requested file doesn't exist yet, you would use mod_rewrite to change the request to a *.zip file to the same or some other PHP script that reads the parameters from the session and produces the file just like you're doing it now. If you use the same PHP script, you would additionally let mod_rewrite add some parameter like "?action=produceFile" to the request and then test for that parameter in the script.
This way you would have two nice entries in your Apache log without having to physically save the file (and probably delete it later).
FYI I found a really good work-around.
Part of the problem was that we wanted to force a "save as" dialogue as many of the users get confused as to where the file gets saved. So this is why I went the
Content-Disposition : attachment
method.
A better method which still invokes the dialogue is to add this to .htaccess
<Files *.zip>
ForceType application/octet-stream
Header set Content-Disposition attachment
</Files>
write the Zip to the fileserver and redirect the page to the zip.
Sure I have to cleanup every night, but it gets logged and it still forces them to choose where they download the file (on pretty much everything but Safari [ there's always one ]).
Cheers,
Niggles

Categories