mando222 mando222 - 6 months ago 10
PHP Question

How do I use HTML5 to download from a non web folder?

I have a webpage for that is for internal use only. It is going to be hosted on a server that is primarily running other processes that generate log files in the /opt/appname/logs/ dir. I have been tasked with making a web interface that will allow these log files to be downloaded to any computer on our network. I am using Apache on Debian. This is what I have so far:

<details>
<summary><b>Download Log Files</b></summary>
<?php
foreach (glob("/opt/appname/logs/*.log") as $filename) {
$file_info = explode("/logs/", $filename);
?>
<a href="<?php echo $filename ?>" download><?php echo $file_info[1] ?></a>
<br>
<?php } ?>
</details>


When I try and download a log file the download looks like it starts but then gives me the message "Failed No file". I have found many posts on line that say you can or can't do this but none of them provide adequate examples. I realize that there are issues with accessing anything outside of the web folders but there has to be some way to do this. I am really at a loss here so any suggestions would be great. Lastly I am self taught so if you see any errors or things that I am not doing best practice please let me know. I am always trying to improve.

Answer

You could create a file download.php. This file can look something like:

Download.php

$fn = $_GET["filename"];

if (is_readable($fn)) {
    header('Content-Description: File Transfer');
    header('Content-Type: text/plain');
    header('Content-Disposition: attachment; filename="'.$fn.'"');        
    readfile($fn);
} else {
   //return a 404 error perhaps.
}

You could then modify your original listing code to:

<details>
   <summary><b>Download Log Files</b></summary>
   <?php
   foreach (glob("/opt/appname/logs/*.log") as $filename) {
      $file_info = explode("/logs/", $filename);
      ?>
      <a href="download.php?filename=<?php echo $filename ?>" download><?php echo $file_info[1] ?></a>
      <br>
   <?php } ?>
</details>

I personally like this method because you can also add extra checks and exceptions in the "download manager".