Friday, March 10, 2017

How to download msg file with PHP

Leave a Comment

I'm currently creating a feature that would allow to download files from remote server. My script works fine for all file types required but it doesn't work for the msg files for some reason (It downloads empty file (0K)). Same behavior in Chrome and IE by the way. I thought the problem is with file size so I've tested to download large zip file and it also work fine, seems that only msg files I've got issue with.

My script:

// Get parameter form html page if(isset($_GET['file_name'])) $file_name = $_GET['file_name'];  $file_name = str_replace('"', '\\"', $file_name); $file_url = 'http://mypath/uploads/' . $file_name;  header('Content-Type: application/octet-stream'); header("Content-disposition: attachment; filename=\"".$file_name."\""); header("Content-Transfer-Encoding: Binary");  readfile($file_url); exit; 

What I'm doing wrong?

P.S. I think possible solution is to archive (zip) .msg file during uploading process and then download it as .zip instead but I'm looking for a better solution.

7 Answers

Answers 1

Expanding my comment into an answer:

I tested your script with a local file, eg. $file_url = 'test.msg';, and this is working here. So I suspect that there is a problem getting the file from the remote server. Can you download the remote .msg file from the server where your PHP script is running by other means than PHP, eg. with wget http://mypath/uploads/test.msg? You could also check the return value of readfile - if it is false, there is an error reading the file. If you cannot download the file or if readfile returns false, then the problem is not in your code, but a server configuration or connectivity issue, which you have to fix first.

Regarding your code: you should sanitize your $_GET['file_name'], to avoid someone passing stuff like ../passwd.

Answers 2

You are trying to use readfile with a URL file location, which is possible only if fopen wrappers have been enabled.

From PHP readfile:

Tip A URL can be used as a filename with this function if the fopen wrappers have been enabled. See fopen() for more details on how to specify the filename. See the Supported Protocols and Wrappers for links to information about what abilities the various wrappers have, notes on their usage, and information on any predefined variables they may provide.

It's not safe and you should use a local system path insted of a URL like this:

// Get parameter form html page if(isset($_GET['file_name'])) $file_name = $_GET['file_name'];  $file_name = str_replace('"', '\\"', $file_name); //$file_url = 'http://mypath/uploads/' . $file_name; // The script is located to one level up directory of the uploads directory // You can change this to fit your script and uploads directory locations $uploads_local_path = __DIR__.'/uploads/'; $file_path = $uploads_local_path.$file_name;  header('Content-Type: application/octet-stream'); header("Content-disposition: attachment; filename=\"".$file_name."\""); header("Content-Transfer-Encoding: Binary");  readfile($file_path); exit; 

and now it works and downloads the file. Just pay attention and have the correct path locations for the uploads directory.

You can even try my local example based on your code here and download a file: http://zikro.gr/dbg/php/dl-file/

A direct link to the download script you can try: http://zikro.gr/dbg/php/dl-file/dodl.php?file_name=1011191_orig.png

Answers 3

Try use another content-type:

header("Content-Type: application/download"); 

Answers 4

Probably a stupid question but, have you tried a simple

$fileurl="http://example.com/file.msg"; $fileContent = file_get_contents($fileurl); file_put_contents($saveDir.$fileName, $fileContent); 

http://php.net/manual/en/function.file-get-contents.php

http://php.net/manual/en/function.file-put-contents.php

Answers 5

Try it

// Get parameter form html page if(isset($_GET['file_name'])) $file_name = $_GET['file_name'];  $file_name = str_replace('"', '\\"', $file_name); $file_url = 'http://mypath/uploads/' . $file_name;  header("Content-Type: application/download"); header("Content-disposition: attachment; filename=\"".$file_name."\""); header("Content-Transfer-Encoding: Binary");  readfile($file_url); exit; 

Answers 6

Try to add a user-agent and accept all MIME types on your request .. by using cURL:

// Get parameter form html page if(isset($_GET['file_name'])) $file_name = $_GET['file_name'];  $file_name = str_replace('"', '\\"', $file_name); $file_url = 'http://mypath/uploads/' . $file_name;  header('Content-Type: application/octet-stream'); header("Content-disposition: attachment; filename=\"".$file_name."\""); header("Content-Transfer-Encoding: Binary");  $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $file_url); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0'); $headerData[] = 'Accept: */*'; curl_setopt($ch, CURLOPT_HTTPHEADER, $headerData); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $data = curl_exec ($ch); $error = curl_error($ch);  curl_close($ch); echo $data; exit; 

Answers 7

I think you must specify the Content-lenght header, and i think disable caching may help too.

for example:

header("Content-length: " . strlen($output); // tells file size header("Pragma: no-cache"); header("Expires: 0"); 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment