【问题标题】:How to prevent file location from showing?如何防止文件位置显示?
【发布时间】:2011-07-21 14:59:21
【问题描述】:

我允许用户将文档上传到服务器。但是,我不希望他们明显看到文件的存储位置。我该怎么做才能让他们仍然获得文件但看不到文件位置。

【问题讨论】:

  • 他们为什么会看到文件的存储位置?
  • 为了给他们提供文件,会有一个下载链接,对吧?
  • 是在谈论上传(客户端向服务器发送文件)还是下载(客户端从服务器拉取文件)?
  • 用户上传文件,然后他们可以下载他们上传的文件。

标签: php filesystems location storage


【解决方案1】:

您可以使用 PHP 查询来完成此操作,假设您使用以下 URL:

http://mysite.com/files.php?file=xyz.pdf

在 files.php 中,您可以检查获取变量文件并具有检索文件的硬编码函数。您可以通过多种方式执行此操作,方法是使用标题强制下载或将文件读入 var 并将其内容打印到页面。比如说像pdf读取文件并将其打印到页面与将其链接到文件一样。

警告:就像使用标题一样,除了文件之外,不会在页面上打印任何内容。如果您阅读文件并打印它,我还建议您仍然声明标题,以便最终用户不会获得作为文件来源的 gobbly goop,即 jpg 或 pdf。

哦,不,我忘记了标题警告,自从 Adob​​e 为 PDF 的开源制作 ISO 以来,我一直遇到标题问题,具体取决于生成 PDF 的应用程序和用户上传 PDF 的浏览器from,标题将是任何来自:

'application/pdf', 'application/x-download','application/octet-stream','application/octet','binary/octet-stream'

所以要小心将上传部分硬编码为标题类型,我知道这个问题是关于下载的,但我只是想我会把它扔在那里。同样使用标题进行下载也没关系,我只需在那里使用标准应用程序/pdf。

【讨论】:

  • +1 这不仅仅是打字速度。这是为了提供一个好的答案。
  • 谢谢。实际上有一个 id 不是一个好主意,所以一旦这个人转到 page.php?id=idjfkldj 就会打开一个弹出窗口,要求他们打开/保存?
  • @KPO 是的,但是您必须创建一个数据库并将 ID 和文件名存储在一个表中。它只会增加更多的工作和更多的安全性。所以这取决于你。
【解决方案2】:

有几种方法可以做到这一点,但我更喜欢使用 .htaccess

所以我的链接看起来像http://example.com/files/filename.zip url 中的额外参数可以使用用户名或密码,例如:

 http://example.com/files/bob/filename.zip

 http://example.com/files/18d52c/filename.zip

然后可以根据数据库检查是否允许用户下载该特定文件,就像您在付款后用于即时下载一样。但基本方法如下:

.htaccess

RewriteRule ^files/(.*)$ serve.php?file=$1

serve.php

<?php 
 if(isset($_GET['file'])){
    $file=basename($_GET['file']);
    //Protect the index.php && serve.php
    if(basename($_GET['file'])=='index.php' || basename($_GET['file'])=='serve.php'){
        header("HTTP/1.1 403 Forbidden");die();
    }
    $downloadFolder="original_location/";
    if(file_exists($downloadFolder.$file)){

        $fsize = filesize($downloadFolder.$file);
        $ctype=finfo_file(finfo_open(FILEINFO_MIME_TYPE), $downloadFolder.$file);

        if(ini_get('zlib.output_compression'))
        ini_set('zlib.output_compression', 'Off');

        header("Pragma: public");
        header("Expires: 0");
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Cache-Control: private",false);
        if(strstr($_SERVER["HTTP_USER_AGENT"],"MSIE")==false) {
            header("Content-Type: application/force-download");
            header('Content-Description: File Transfer');
        }else{
            header("Content-Type: $ctype");
        }
        header("Content-Disposition: attachment; filename=\"".basename($file)."\";" );
        header("Content-Transfer-Encoding: binary");
        header("Content-Length: ".$fsize);

        ob_clean();
        flush();
        readfile('original_location/'.$file);
    }else{
        header("HTTP/1.0 404 Not Found");
    }
    die();
 }
 header("HTTP/1.0 404 Not Found");
?>

original_location/index.php

header("HTTP/1.1 403 Forbidden");

【讨论】:

  • 你可以用php.net/manual/en/ref.fileinfo.php替换整个mime-type业务...
  • 感谢我添加了您的建议。
  • +1 漂亮的实现有 Lawrence,它涵盖了所有的基础和错误场景。我现在几乎为我的回答感到羞耻,我的意思是我基​​本上告诉他同样的事情,但你的代码涵盖了所有基础,如果你不介意我想将它添加到我的 sn-p 库中,并参考你当然。
  • 绝对,我回答的问题有一半是小sn-ps的存储;p
【解决方案3】:

使用可以映射到真实文件的随机唯一 ID 存储它,然后使用在实际文件上执行 readfile() 的脚本提供它。

http://php.net/readfile 文档也有一个关于如何强制下载的示例。

【讨论】:

  • 真的吗?相同的答案并在我的几秒钟内发布但已经投了赞成票?哦,我得打字快一点,我想蒂诺做得很好。
  • 我并不是想快速进入。我刚刚发布了我认为足以让他进一步调查并找到可行的方案的信息。
  • 哦,不,我只是在说我运气不好,没什么大不了的,这一切都是在开玩笑,我没有沮丧或任何事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2021-06-05
  • 1970-01-01
  • 1970-01-01
  • 2020-02-02
相关资源
最近更新 更多