【问题标题】:Download using Yii::app()->request->SendFile returns corrupted file使用 Yii::app()->request->SendFile 下载返回损坏的文件
【发布时间】:2016-02-26 08:00:49
【问题描述】:

我一直在尝试从这样的特定目录下载我上传的文件:

Yii::app()->request->SendFile($model->statement, 
                        file_get_contents($path.$model->statement)
                        ); 

它可以识别文件并以正确的名称和格式下载它,但我得到的不是 74KB 的文件,而是 1KB 的损坏文件。试过其他文件如.doc、.pdf,还是一样。

我不完全确定 file_get_contents 的实际作用,因为我从我找到的一个例子中得到了这个。

要下载的文件以前是使用上传的

<div class="row">
    <?php echo $form->labelEx($model, 'statement'); ?>
    <?php echo $form->fileField($model, 'statement', array('size' => 36, 'maxlength' => 255)); ?>
    <?php echo $form->error($model, 'statement'); ?>
</div>

在_form.php中并调整控制器中的actionCreate:

public function actionCreate($id)
{
    $model=new Witness;
    $model->ip_id = $id;

    // Uncomment the following line if AJAX validation is needed
    // $this->performAjaxValidation($model);

    $path = Yii::app()->basePath . '/modules/iris/statements';
    if (!is_dir($path)) {
        mkdir($path);
    }   

    if(isset($_POST['Witness']))
    {
        $model->attributes=$_POST['Witness'];

        if (@!empty($_FILES['Witness']['name']['statement'])) {
            $model->statement = $_POST['Witness']['statement'];
            if ($model->validate(array('statement'))) {
                $model->statement = CUploadedFile::getInstance($model, 'statement');
            } else {
                $model->statement = '';
            }

            $model->statement->saveAs($path . '/' . time() . '_' . str_replace(' ', '_', strtolower($model->statement)));

            //$model->doc_type = $model->statement->getType();
            //$model->doc_size = $model->statement->getSize();
        }

        $model->statement = time() . '_' . str_replace(' ', '_', strtolower($model->statement));


        if($model->save())
            $this->redirect(array('ip/view','id'=>$model->ip_id));
    }

    $this->render('create',array(
        'model'=>$model,
    ));
}

上传的文件可以毫无问题地打开。知道为什么下载损坏了吗?下载前是否必须先指定文件的类型/大小?

【问题讨论】:

    标签: php yii download yii1.x sendfile


    【解决方案1】:

    对于一个 1kb 的文件,听起来你的服务器在设置标头后抛出了一个 php 错误。

    用文本编辑器打开下载的文件并检查内容。

    【讨论】:

    • 哦,现在我明白了。使用文本编辑器打开文件,它显示文件的 $path。所以现在我知道 file_get_contents 实际上用它的参数覆盖了我的文件。我最好重新检查一下 SendFile 函数的参数。
    • 仍然找不到正确的方法。是否可以使用 (public void sendFile(string $fileName, string $content, string $mimeType=NULL, boolean $terminate=true) 函数?$content 的参数应该是什么?
    • 第二个参数应该是你文件的内容。您的示例代码看起来正确。试试var_dump(file_get_contents($path.$model-&gt;statement));exit; 看看会输出什么。
    • 感谢您的建议!但是,我为此找到了另一种解决方案。看我上面的回答。
    【解决方案2】:

    我找到了另一种解决方案,而不是使用 SendFile 函数。把这个放到视图文件中生成下载链接:

    CHtml::link('Click to download file', array('ip/download&id='.$model->file_id));
    

    其中“ip”是型号名称。这会将 file_id 传递给在 controller.php 中创建的函数 actionDownload:

    public function downloadFile($fullpath){
        if(!empty($fullpath)){
            header("Content-type:application/pdf"); //for pdf file
            //header('Content-Type:text/plain; charset=ISO-8859-15');
            //if you want to read text file using text/plain header
            header('Content-Disposition: attachment; filename="'.basename($fullpath).'"');
            header('Content-Length: ' . filesize($fullpath));
            readfile($fullpath);
            Yii::app()->end();
        }
    }
    
    public function actionDownload($id){
        $model=Ip::model()->findByPk($id);
        $path = Yii::app()->basePath . 'location of file to be downloaded'.$model->filename;
        $this->downloadFile($path);
    }
    

    这应该会完全下载文件。不用担心内容类型,我已经尝试了所有常见的文件类型(.pdf、.doc、.ppt、.png、.jpg),一切都很好。

    【讨论】:

      【解决方案3】:

      在 Yii2 中,sendFile() 签名是

      public $this sendFile ( $filePath, $attachmentName = null, $options = [] )
      

      发送文件:

      Yii::$app->response->sendFile('test.zip');
      

      对于那些获得完整文件但仍然损坏的人:

      你应该检查其他php文件是否正在打印输出,有时关闭PHP标签后的空格会导致问题。

      From here

      【讨论】:

      • 这个问题是关于 Yii 1.1,你的答案是 Yii 2。
      • @rob006,当我回答时,没有yii1.x标签,只有yii
      • OP 使用的是Yii::app(),所以这显然是 Yii 1.1。您的回答可能令人困惑,因为 sendFile() 在 Yii 2 中的签名与在 Yii 1.1 中的签名不同。
      • 不,不明显。我指出我的答案的第一部分是针对 Yii2 的。
      【解决方案4】:

      如果您查看sendFile 的参数列表,您可以看到第三个参数是mimeType。事实上,您没有提供 HTTP 标头响应,因此我对您的初步建议是尝试明确指定 Content-Type 响应标头:

      Yii::app()->request->sendFile(
         "Youfile.pdf",
         file_get_contents('path/to/file'), 
         'application/pdf'
      );
      

      【讨论】:

        猜你喜欢
        • 2019-01-19
        • 1970-01-01
        • 2013-05-19
        • 1970-01-01
        • 1970-01-01
        • 2017-05-27
        • 2018-04-08
        • 1970-01-01
        • 2017-05-22
        相关资源
        最近更新 更多