从带有文件系统的 AWS S3 下载的 Laravel 文件已损坏
Posted
技术标签:
【中文标题】从带有文件系统的 AWS S3 下载的 Laravel 文件已损坏【英文标题】:Laravel file downloaded from AWS S3 with Filesystem gets corrupted 【发布时间】:2016-09-22 09:46:19 【问题描述】:我正在使用 Laravel 文件系统将文件上传到 Amazon S3。但是,当我下载文件损坏时,上传过程效果很好。我已经从 S3 存储桶手动下载了文件,这样文件就不会损坏,所以我认为问题不在于上传。
我正在上传这样的文件:
/**
* Upload the file to Amazon S3.
*
* @param UploadedFile $file
* @param $path
* @return $this|bool
*/
protected function upload(UploadedFile $file, $path)
$this->filename = $path . '/' . time() . '_' . str_replace(' ', '-', $file->getClientOriginalName());
$disk = Storage::cloud();
if ($disk->put($this->filename, fopen($file, 'r+')))
$this->save();
return $this;
return false;
要下载,我试过这个:
/**
* @param Document $document
* @return Response
*/
public function download(Document $document)
$file = Storage::cloud()->get($document->path);
$file_info = new finfo(FILEINFO_MIME_TYPE);
return response($file, 200)->withHeaders([
'Content-Type' => $file_info->buffer($file),
'Content-Disposition' => 'inline; filename="' . $document->name . '"'
]);
还有这个:
/**
* @param Document $document
* @return Response
*/
public function download(Document $document)
$stream = Storage::cloud()->getDriver()->readStream($document->path);
$file = stream_get_contents($stream);
$file_info = new finfo(FILEINFO_MIME_TYPE);
return response($file, 200)->withHeaders([
'Content-Type' => $file_info->buffer($file),
'Content-Disposition' => 'inline; filename="' . $document->name . '"'
]);
通过这两个下载功能,我得到了文件,但是它们已损坏。任何帮助表示赞赏!
【问题讨论】:
$file_info->buffer($file)
的值是多少?
@maiorano84 我将主要使用 PDF、Doc/x 和 Dwg。根据流式传输的文件,我从$file_info->buffer($file)
得到"application/pdf"
、"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
或"image/vnd.dwg"
只是为了搞笑,尝试将标题设置为以下内容:[ 'Content-Type' => 'application/octet-stream', 'Content-Disposition' => 'attachment; filename="' . $document->name . '"' ]
@maiorano84 我仍然在 Word 文档中得到以下信息:Word 在 file.docx 中发现不可读的内容。是否要恢复此文档的内容?如果您信任此文档的来源,请单击“是”。
由于我以前从未使用过存储层,所以我很难说断开连接可能在哪里。也就是说,Laravel 响应对象确实有一个下载方法。看看this answer 是否有助于为您简化流程。
【参考方案1】:
问题在于输出缓冲区包含空格。在返回响应之前使用ob_end_clean()
解决了这个问题,但是在打开<?php
标记之前在文件上找到一个空格时,不需要使用ob_end_clean()
。
这是不使用预签名网址的代码:
/**
* Download document from S3.
*
* @param Document $document
* @return Response
*/
public function download(Document $document)
$s3Client = Storage::cloud()->getAdapter()->getClient();
$stream = $s3Client->getObject([
'Bucket' => 'bucket',
'Key' => $document->path
]);
return response($stream['Body'], 200)->withHeaders([
'Content-Type' => $stream['ContentType'],
'Content-Length' => $stream['ContentLength'],
'Content-Disposition' => 'inline; filename="' . $document->name . '"'
]);
【讨论】:
以上是关于从带有文件系统的 AWS S3 下载的 Laravel 文件已损坏的主要内容,如果未能解决你的问题,请参考以下文章