代码之家  ›  专栏  ›  技术社区  ›  rhodesjason

使用PHP创建.jpg文件的下载链接

  •  2
  • rhodesjason  · 技术社区  · 17 年前

    现在,我知道我可以直接链接到.jpg文件,但这需要用户在新窗口中打开图像,右键单击,另存为…,等等。相反,我希望“下载组件”链接立即启动文件下载。

    PHP.net似乎建议使用readfile(),因此每个“下载Comp”链接都被回音为“?Download=true&g={$gallery}&i={$image}”。

    然后,在页面顶部,我捕捉到$_GET['download']var是否已设置,如果已设置,则运行以下代码:

    if(isset($_GET['download'])) {
    $gallery = $_GET['g'];
    $image = $_GET['i'];
    $file = "../watermark.php?src={$gallery}/images/{$image}";
    header('Content-Description: File Transfer');
        header('Content-Type: application/jpeg');
        header('Content-Disposition: attachment; filename='.basename($file));
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: public');
        header('Pragma: public');
        header('Content-Length: ' . filesize($file));
        ob_clean();
        flush();
    readfile($file);
    

    链接需要很长时间,然后会弹出一个对话框提示,要求您打开或保存该文件,但一旦您保存并尝试打开该文件,它会说该文件已损坏,无法打开。

    有什么想法吗?

    5 回复  |  直到 17 年前
        1
  •  4
  •   mcrumley    17 年前

    不要将$file设置为相对url。readfile函数将尝试访问服务器上的php文件。那不是你想要的。在您的情况下,看起来watermark.php文件将发送您想要的内容,因此您可以只设置它所需的环境并将其包含在内。

    <?php
    if(isset($_GET['download'])) {
        $gallery = $_GET['g'];
        $image = $_GET['i'];
        $_GET['src'] = "{$gallery}/images/{$image}";
    
        header('Content-Description: File Transfer');
        header('Content-Type: image/jpeg');
        header('Content-Disposition: attachment; filename='.basename($image));
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: public');
        header('Pragma: public');
        ob_clean();
        include('../watermark.php');
        exit;
    }
    

    另一种(更简单的)方法是修改watermark.php。添加一个查询参数,使其发送正确的标题以强制下载并链接到该标题

    <a href="watermark.php?src=filename.jpg&download=true)">...</a>
    

    <?php
    if (isset($_GET['download']) && $_GET['download'] == 'true') {
        header('Content-Description: File Transfer');
        header('Content-Type: image/jpeg');
        header('Content-Disposition: attachment; filename='.basename($src));
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: public');
        header('Pragma: public');
    }
    // continue with the rest of the file as-is
    

    另外,不需要调用flush()。此时不应该有任何输出要发送,因此没有必要。

        2
  •  1
  •   Jed Smith    17 年前
    header('Content-Type: image/jpeg');
    

        3
  •  1
  •   Eric Petroelje    17 年前

    我想你可能需要听从电话 readfile() exit() 以确保没有其他内容写入输出缓冲区。

        4
  •  1
  •   easement    17 年前

    如果有人进来怎么办:

    $g = '../../../../../../';
    $i = '../../sensitive file at root';
    

    让画廊目录中的.htaccess(如果您使用的是apache)i将JPEG作为下载文件而不是普通文件提供,怎么样。

        5
  •  0
  •   Marc W    17 年前

    还有,试试看 file_get_contents() readfile() . 我发现它在更多的情况下有效。我还建议您使用 ob_flush() 输出图像数据之后。我从来都不需要使用 ob_clean() 或 flush() 让这类事情运作起来。

    正如Eric所说,你也可以打电话给 exit()

    推荐文章