【问题标题】:PHP - send file to userPHP - 向用户发送文件
【发布时间】:2011-02-22 08:56:55
【问题描述】:

我在磁盘上有一个 pdf 文件,当他们向 php 脚本发出请求时,我需要将其发送给用户,最好的方法是什么?

【问题讨论】:

    标签: php


    【解决方案1】:

    如果您使用的是 Apache 或 Lighty,那么从性能的角度来看,“最好”的方法是使用 X-Sendfile 标头。看这个教程:https://www.h3xed.com/programming/how-to-use-x-sendfile-with-php-apache

    【讨论】:

    【解决方案2】:

    假设它在服务器上:

    readfile() — 输出一个文件

    注意:只是写作

    readfile($file);
    

    行不通。这将使客户端永远等待响应。您需要定义标题以使其按预期方式工作。 See this example from the official PHP manual:

    <?php
    $file = 'monkey.gif';
    
    if (file_exists($file)) {
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename='.basename($file));
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
        header('Content-Length: ' . filesize($file));
        ob_clean();
        flush();
        readfile($file);
        exit;
    }
    ?>
    

    【讨论】:

    • 在 IE8/Vista 下为我工作。您收到错误消息还是只是加载了一个白页?
    • 这个例子包含很多废话。 HTTP 中不存在 Content-Description。 Content-Type 应该设置为实际的媒体类型,或者根本没有。 Content-Disposition 的代码将为许多文件名生成不正确的标题。 HTTP 中不存在 Content-Transfer-Encoding。另请参阅 blogs.msdn.com/b/ieinternals/archive/2012/05/16/… 关于 Cache-Control。
    • @Julian Reschke:为什么它会在 php.net 上正式发布?
    • 我觉得this answer 可能会帮助那些不确定标题的人。
    • 我发现 Armand Niculescu 的 this blogpost(和 companion script(通过 'Hargobind' 做了一些改进))非常很有帮助。顺便说一句,这两个链接在 archive.org 中都有多个副本。
    【解决方案3】:

    这是您使用 PHP 发送文件所需的内容:

    $filename = "whatever.jpg";
    
    if(file_exists($filename)){
    
        //Get file type and set it as Content Type
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        header('Content-Type: ' . finfo_file($finfo, $filename));
        finfo_close($finfo);
    
        //Use Content-Disposition: attachment to specify the filename
        header('Content-Disposition: attachment; filename='.basename($filename));
    
        //No cache
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
    
        //Define file size
        header('Content-Length: ' . filesize($filename));
    
        ob_clean();
        flush();
        readfile($filename);
        exit;
    }
    

    正如 Julian Reschke 评论的那样,经过验证的答案可能有效,但它充满了无用的标题。 content-type 应设置为文件的真实类型,否则某些浏览器(尤其是移动浏览器)可能无法正常下载。

    【讨论】:

    • 谢谢你,特别是ob_clean(); flush();
    • 能否将 cmets 添加到 ob_cleanflush 位?他们解决了哪些潜在问题?
    • Content-Disposition 需要在文件名周围加“”,以防有空格
    【解决方案4】:

    好的,所以我不是 PHP 专家,我只能将其他一些 PHP 的 sn-ps 组合在一起来实现我需要它做的事情,我认为我最好将此解决方案发布在一些论坛提出了同样的问题,但我自己无法工作。似乎在任何地方都没有解决方案,所以就在这里。这个对我有用... 好的,首先我创建了 PDF 表单并添加了一个按钮,然后提交表单。在此提交表单的操作中,我告诉它 PDF 完整文档。 然后我给它一个指向 php 页面的 URL 链接,例如 mail_my_form.php 然后我创建了一个 php 表单,并将其命名为与上面相同... mail_my_form.php 最后一件事是在此 php 代码所在的根目录中创建一个名为 pdfs 的文件夹。 (因此,如果您将 php 放在一个名为 email 的文件夹中,那么在 email 的文件夹中,您需要另一个名为 pdfs 的文件夹) 现在这个脚本的作用是: 将 PDF 保存为文件名 pdfs。 然后它将文件附加到电子邮件并发送。 然后它从文件夹 pdfs 中删除文件以节省空间。 (如果您愿意,也可以使用删除功能将表单保存在 FTP 上。
    在这里。

    <?php 
    $fileatt = date("d-m-Y-His") . ".pdf";  // Creates unique PDF name from the date 
    copy('php://input',"pdfs/".$fileatt); // Copies the pdf form data to a folder named pdfs 
    $fileatt = "pdfs/".$fileatt; // Path to the file gives the pdfs folder plus the unique file name we just assigned
    $fileatt_type = "application/pdf"; // File Type 
    $fileatt_name = "Application Form_".$fileatt.".pdf"; // Filename that will be used for the file as the attachment when it is sent
    
    $email_from = "mywebsite"; // Who the email is from 
    $email_subject = "Completed online Applications"; // The Subject of the email 
    $email_message = "Please find a recent online application attached.
    ";
     $email_message .= "Any problems please email me...
    "; // Message that the email has in it 
    
    $email_to = "youremail@yourserver.com"; // Who the email is to 
    
    $headers = "From: ".$email_from;
    
    //no need to change anything else under this point
    
    $file = fopen($fileatt,'rb'); 
    $data = fread($file,filesize($fileatt)); 
    fclose($file); 
    
    $semi_rand = md5(time()); 
    $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x"; 
    
    $headers .= "\nMIME-Version: 1.0\n" . 
    "Content-Type: multipart/mixed;\n" . 
    " boundary=\"{$mime_boundary}\""; 
    
    $email_message .= "This is a multi-part message in MIME format.\n\n" . 
    "--{$mime_boundary}\n" . 
    "Content-Type:text/html; charset=\"iso-8859-1\"\n" . 
    "Content-Transfer-Encoding: 7bit\n\n" . 
    $email_message .= "\n\n"; 
    
    $data = chunk_split(base64_encode($data)); 
    
    $email_message .= "--{$mime_boundary}\n" . 
    "Content-Type: {$fileatt_type};\n" . 
    " name=\"{$fileatt_name}\"\n" . 
    //"Content-Disposition: attachment;\n" . 
    //" filename=\"{$fileatt_name}\"\n" . 
    "Content-Transfer-Encoding: base64\n\n" . 
    $data .= "\n\n" . 
    "--{$mime_boundary}--\n"; 
    
    $ok = @mail($email_to, $email_subject, $email_message, $headers); 
    
    if($ok) { 
    unlink($fileatt); //NOW WE DELETE THE FILE FROM THE FOLDER pdfs 
    Header("Location: nextpage.php"); //where do we go once the form has been submitted.
    
    } else { 
    die("Sorry but the email could not be sent. Please go back and try again!"); 
    } 
    ?>
    

    希望这对你们中的一些人有所帮助。

    理查德·威廉姆斯

    【讨论】:

      猜你喜欢
      • 2014-06-05
      • 1970-01-01
      • 1970-01-01
      • 2012-10-27
      • 2014-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多