php强制下载使用header()破解下载的文件

时间:2012-09-17 14:17:09

标签: php header download buffer liferay

首先,我想告诉我在标头使用方面我很新手并且使用输出缓冲区。所以即时开发php portlet for liferay,我有一些文件下载问题。我试着用'a href'来做这件事,但问题是通过php上传的文件在apache刷新之前是不可用的,所以我尝试了另一种方式使用header()函数。

所以我会尝试解释我的问题。当我尝试在简单的PHP项目上使用代码时,它工作正常:

    <?php

$path = "/mysecretdir/upload/"; // change the path to fit your websites document structure
$fullPath = $path.$_GET['download_file'];

if ($fd = fopen ($fullPath, "r")) {

    $fsize = filesize($fullPath);

    $path_parts = pathinfo($fullPath);
    $ext = strtolower($path_parts["extension"]);

    switch($ext) {

        case "pdf":
            $ctype = "application/pdf";
            break;
        case "exe":
            $ctype = "application/octet-stream";
            break;
        case "zip":
            $ctype = "application/zip";
            break;
        case "doc":
            $ctype = "application/msword";
            break;
        case "xls":
            $ctype = "application/vnd.ms-excel";
            break;
        case "ppt":
            $ctype = "application/vnd.ms-powerpoint";
            break;
        case "gif":
            $ctype = "image/gif";
            break;
        case "png":
            $ctype = "image/png";
            break;
        case "jpeg":
            $ctype = "image/jpg";
            break;
        case "jpg":
            $ctype = "image/jpg";
            break;
        case "mp3":
            $ctype = "audio/mp3";
            break;
        case "wav":
            $ctype = "audio/x-wav";
            break;
        case "wma":
            $ctype = "audio/x-wav";
            break;
        case "mpeg":
            $ctype = "video/mpeg";
            break;
        case "mpg":
            $ctype = "video/mpeg";
            break;
        case "mpe":
            $ctype = "video/mpeg";
            break;
        case "mov":
            $ctype = "video/quicktime";
            break;
        case "avi":
            $ctype = "video/x-msvideo";
            break;
        case "src":
            $ctype = "plain/text";
            break;
        default:
            $ctype = "application/force-download";
    }

    header("Pragma: public");

    header("Expires: 0");

    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");

    header("Cache-Control: private",false);

    header("Content-type: " . $ctype);

    header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\"");

    header("Content-Transfer-Encoding: binary");

    //header("Content-length: $fsize");
    header("Cache-control: public"); //use this to open files directly    

    while(!feof($fd)) {
        echo fread($fd, 4096); 
    flush();
    }
}
fclose ($fd);
?>
来自index.php的

我用href =“download.php来调用它吗?download_file = / something /”

好的,但现在重点。当我在liferay portlet中使用它时,文件很奇怪。它将整个生成的HTML文件放在创建的文件中。所以它破碎了。我不知道为什么。我不知道标题是否从其他地方发送一些信息,也不知道如何解决它。

我正在寻找一些解决方案的时间,但不知道如何为标题做某种“会话”,因为我认为它们存在问题。 Becasue没有回声它只打印文件的内容和其他项目 - 更简单的PHP应用程序不作为门户网站的一部分工作!但也许我错了。

那么请有人帮帮我吗?有什么建议吗?

2 个答案:

答案 0 :(得分:1)

我无法帮助你解决特定的php-portlet问题(我从未使用过Liferay与php),但听起来你得到的整个页面HTML都是在你下载的文件周围生成的。这是您在呈现portlet时获得的结果:Portlet始终嵌入在HTML页面中,因此您无法在HTTP级别上使用portlet的标准呈现输出提供特定标头。

您想要的是portlet的serveResource生命周期阶段。这将允许您提供不属于页面的内容,但您可以完全控制下载和HTTP标头。如何使用php portlet,我将不得不留给你。

编辑(其他信息):正如您在评论中提到的那样,我发现了一个较旧的(可能需要进行调整)Wiki article,其中讨论了使用state = exclusive来做同样的事情技巧 - 而不是我上面建议的serveResource。我不知道这是由于文章的年代还是因为PHP portlet不支持该生命周期,但您可能会在相关和链接的文章中找到相关内容。注意:serveResource会 - 如果我没记错 - 生成一个p_p_lifecycle = 2参数,而这个例子使用p_p_lifecycle = 0(render)和p_p_state = exclusive。如果这符合您的要求,请尝试

但是,请考虑Marc B关于您的代码不安全且硬编码太多的评论。针对潜在问题有更好的解决方案 - 例如Liferay提供文档库来开箱/下载文件。而且这没有这些问题。

答案 1 :(得分:0)

如果您使用空格或任何其他字符启动PHP文件,标题将无法正常工作,显示/下载将失败。确保<?php标记之前没有任何内容。

除此之外,这应该有用(如果你没有在浏览器中收到错误)。

另一方面,如果您看到实际的PHP代码,则您的服务器不支持PHP。