views:

514

answers:

2

Hi,

BACKGROUND:

I have built a web application for a client which allows them to save excel files to the server.

When I first built the application I stored these files in an uploads folder and linked to them directly from pages within the application (eg File).

On reflection this wasn't very secure so I changed the uploader file to store the files above the web root and thereby prevent direct access.

I deliver the files back to the user by way of a php 'retriever' file (eg File). The file (after some user authentication checks) looks like this:

header("Content-type: application/octet-stream");
$_file = $_GET['filename'];
$sPattern = '/\s*/m';
$sReplace = '';

$_strippedfile = preg_replace( $sPattern, $sReplace, $_file );
header("Content-Disposition: attachment; filename=".$_strippedfile."");
echo file_get_contents('/var/www/uploads/'.$_file);

PROBLEM:

The above all works fine unless the user chooses to 'open' rather than 'save' in internet explorer. Excel attempts to open the file and throws '...could not be found. Check the spelling of the file name, and verify that the file location is correct'.

I've googled that error and it appears that it's to do with the length of the filename (including the path). Unfortunately the path to temporary internet files is out of my control so was wondering if there was a way to force the user to save the file rather than open it? [Apparently this can be configured locally but a) my clients aren't very technical and b) because they're on a corporate network all admin rights are tied down.]

Any other ideas welcomed.

+1  A: 

I don't think so. Opening the file in the associated application is a basic function offered by the browser, and can't be influenced.

This is sad, because there is a additional User Experience problem here. I Open a file from the Internet, and Excel lets me edit it. So when I save it, I can safely assume the changes go back to the Internet. Right? Or at least, they're not lost. Right? Right? Try explaining to a non-technical user who has worked on such a document for two hours that their work is lost.

But I digress. You may want to play around with the download headers some more. I find it hard to imagine that Excel files can't be opened directly after downloading.

Can you try sending a Content-type: application/ms-excel? Or will that automatically open, and not offer to save?

Also, does your file name contain any special characters / Umlauts? Slashes? Spaces as mentioned by Gipsy King? All those can lead to problems when opening.

Pekka
It seems you're right about special characters but internet explorer seems to be putting them in itself!? It seems to be saving the file with additional square brackets eg. myfile[1].xls in temporary internet files even when I've cleared out the temporary internet files folder. I've tested with firefox and that's saving as myfile.xls . Bizarre. Any ideas?
Derek
P.S. Thanks for the quick response!
Derek
The brackets come from a file of the same name already existing in the folder, taht should be o.k. If there are no other special characters `äöü/$%` etc., it's really strange why this wouldn't work...
Pekka
+2  A: 

You can prevent Open of files in IE8 by sending the header

X-Download-Options: noopen

In earlier versions, you need to add a DOWNLOADOPTIONS meta tag to the page that contains the XLS file.

But it seems likely that the problem you're hitting has nothing to do with the length of the filename and everything to do with the caching headers on the response. You need to make sure that your file is marked as cacheable (e.g. Cache-Control: private) especially if you're using HTTPS. See http://stackoverflow.com/questions/1506874/download-file-over-https-in-ie-5-5-iis-5-0 for further discussion.

EricLaw -MSFT-
Sorted! You were right about the cache-control setting. Got the following from a tutorial: //Enable caching // seconds, minutes, hours, days $expires = 60*60*24*14; header("Pragma: public"); header("Cache-Control: maxage=".$expires); header('Expires: ' . gmdate('D, d M Y H:i:s', time()+$expires) . ' GMT');And now the files open without a problem.Thanks!
Derek