【问题标题】:serving .docx files through my webserver are corrupt when opened通过我的网络服务器提供的 .docx 文件在打开时已损坏
【发布时间】:2012-08-17 05:45:27
【问题描述】:

虽然我在这里找到了答案: Serving .docx files through Php 但是当我尝试通过 php 下载和打开 docx 服务器时,我仍然收到文件损坏的错误 也许您会发现我的代码有问题。 .doc 工作正常,但失败的是 docx。

$parts = pathinfo($doc);
$docFile = $userDocRoot.$doc;
if ( !file_exists($docFile) ){
    throw new Exception("Can not find ".$parts ['basename']." on server");
}
if ( $parts['extension'] == 'docx' ){
    header('Content-type: application/vnd.openxmlformats- officedocument.wordprocessingml.document');
    header('Content-Disposition: attachment; filename="'.$parts['basename'].'"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    ob_clean();
    flush();
    readfile($docFile);
}else{
   header('Content-type: application/msword');
   header('Content-Disposition: attachment; filename="'.$parts['basename'].'"');
   readfile($docFile);
}

【问题讨论】:

  • $docFile的内容是真实的Word文档,还是html标记等其他格式?
  • 是的,我实际上创建了一个doc文件并将其保存为docx并上传到服务器
  • 您在 Content-Type 中有一个空格。这是这里的错字还是您的代码中的错字?
  • 不只是剪切/粘贴到这个问题
  • 您将文件保存为docx 文件,还是将其重命名为docx

标签: php mime-types


【解决方案1】:

这是一个对我有用的代码(经过大约 5 个小时的折腾):

           // headers to send your file
           header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
           header("Content-Length: " . filesize($original_file));
           header('Content-Disposition: attachment; filename="' . $new_filename . '"');
           ob_clean();
           flush();
           readfile($original_file);
           exit;

希望对你有帮助:)

【讨论】:

    【解决方案2】:

    我遇到了同样的问题。

    原因是,在我的 php-file 的某个地方隐藏了两个空格。

    删除它们解决了问题。

    1. headerreadfile-statements前面添加“//
    2. readfile-statement. 之后写echo "test";
    3. 然后查看HTML源代码,前面是否有空格 “测试”。

    【讨论】:

      【解决方案3】:

      我刚刚花了一段时间研究为什么我的 DOCX 文件被损坏并偶然发现了这个问题……但我也在其他地方找到了答案……

      $fsize = filesize($docFile);
      header("Content-Length: ".$fsize);
      

      这给了我寻找的工具...关键是filesize() 需要文件的基本名称才能获得准确的文件大小!

      调整我的代码:

      header("Content-Length: ".filesize(basename($file)));
      

      这现在按预期提供 DOCX(我已将 Content-type 设置为“application/vnd.openxmlformats-officedocument.wordprocessingml.document”),我不必像其他人报告的那样“修复”文档... (我也发现修复有用)

      【讨论】:

      • 这是正确答案。我刚刚指定了Content-typeContent-Disposition。添加Content-Length 解决了这个问题。谢谢!
      【解决方案4】:

      我的解决方案是添加

       $fsize = filesize($docFile);
       header("Content-Length: ".$fsize);
      

      感谢大家的帮助

      【讨论】:

      • 您在我发布解决方案前 2 分钟得到了自己的答案。 :-)
      【解决方案5】:

      您的代码中有一些额外的空格会导致它失败。

      尝试使用此代码:

      $parts = pathinfo($doc);
      $docFile = $userDocRoot . $doc;
      if(!file_exists($docFile)){
          throw new Exception('Can not find ' . $parts['basename'] . ' on server');
      }
      if($parts['extension'] == 'docx') {
          header('Content-type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
          header('Content-Disposition: attachment; filename="' . $parts['basename'] . '"');
          header('Expires: 0');
          header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
          header('Pragma: public');
          ob_clean();
          flush();
          readfile($docFile);
      } else {
          header('Content-type: application/msword');
          header('Content-Disposition: attachment; filename="' . $parts['basename'] . '"');
          readfile($docFile);
      }
      

      如果还是不行,试试把headerreadfile这行注释掉,看看有没有错误。

      另外,我建议您对照白名单检查文件名,这样人们就无法下载带有密码的 PHP 文件等。

      【讨论】:

      • 没有区别 :-( 注释掉 header 和 readfile 时没有错误
      • @randy 如果不注释掉readfile 行会怎样?另外,如果您在记事本中打开生成的文件,您会看到任何错误吗?
      • 如果我注释掉除了 readfile 之外的所有内容,我会在页面上看到一堆不可打印的字符,这是有道理的,因为我猜它是一个 doc 文件。
      • 您可以尝试创建一个测试文档,将其保存为docx,然后通过您的脚本访问它吗?
      • @randy 好的。尝试通过您的网络浏览器直接访问它。
      猜你喜欢
      • 2012-07-21
      • 1970-01-01
      • 2013-10-24
      • 1970-01-01
      • 2020-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多