PHP MongoDB PDF上传blob问题



我允许用户上传image/doc文件,为此我使用MongoDB GridFS。我能够上传有限大小的images, doc files and pdf(约为5 MB),并根据需要存储(单个条目),然后用于获取数据并在前端显示。

上传文件的代码如下

$conn = new MongoClient();
$db = $conn->selectDB('mydb');
$gridfs = $db->getGridFS('uploads');
$ObjId = new MongoId();
$uniqId = (string)$ObjId;
$uploadedIds = array();
foreach ($_FILES as $file) {
    $id = $gridfs->storeFile($file['tmp_name'], array("metadata" => array(
        'filename' => $file['name'],
        'type' => $file['type'],
        "id"=> 2,
        "parentId" => "1",
        "name" => "Employee Reference",
        "title" => "Employee Reference",
        "isFolder" => 1
    )));
    $id = $gridfs->storeFile($file['tmp_name'], array(
        '_id' => $ObjId,
        "id" => $uniqId,
        'filename' => $file['name'],
        'type' => $file['type'],
        "parentId" => "10",
        "title" => $file['name'], 
        isFolder" => 0
    ));
}
$conn->close();

但当我尝试上传一个大小约为8 MBPDF时,它会以以下格式存储数据。

{
    "_id" : ObjectId("54226f4c920662240a000080"),
    "filename" : "blob",
    "type" : "application/octet-stream",
    "title" : "blob",
    "uploadDate" : ISODate("2014-09-24T07:14:20.000Z"),
    "length" : 338277,
    "chunkSize" : 261120,
    "md5" : "d4f9269491c30a0ab086b3bab02c81ee"
}

正如您在上面看到的,文件根据length进行划分,对于单个PDF,它会插入大约8个条目。

如何在一个文件中获取大文件的数据,并在前端显示文件名和其他详细信息?

谢谢。

没有理由在同一文件上多次调用storeFile()。这将创建一个额外的fs.files文档和冗余的fs.chunks文档。

在对storeFile()的第一次调用中,您将所有元数据嵌套在metadata字段下,这可能不是您想要的。GridFS存储方法的$metadata自变量基本上被合并到将要创建的fs.files文档中,这就是为什么该文档暗示在$metadata中使用_id(如果提供的话);否则,驱动程序将生成一个新的MongoId实例。对storeFile()的第二次调用中的$metadata参数看起来更为典型。

由于您在元数据数组中包含了一个isFolder字段,我认为您可能错误地认为GridFS支持目录结构。GridFS不过是一种约定,由各种驱动程序共享,用于在集合中存储二进制Blob。fs.files记录保存元数据(此处概述了核心字段),所有二进制数据存储在一个或多个相关的fs.chunks文档中(链接回fs.files标识符)。

可以通过元数据字段的方式用GridFS模拟目录结构,但这不是一个常用功能。例如,您可以添加一个path元数据字段,该字段将始终存储规范的目录路径(例如,您的应用程序将在存储之前将/foo/bar/../bar规范化为/foo/bar),然后创建一个要求pathfilename组合唯一的fs.files索引。这将完全取决于您的应用程序来跟踪这一点。


由于您正在存储上传的文件(在$_FILES中引用),因此可能需要使用MongoGridFS::storeUpload(),它将字段名(即$_FILES键)作为第一个参数,并根据用户提供的名称自动填充fs.files文档中的filename字段。通常,客户端文件名是任意的(所以不要盲目相信它或期望它是唯一/准确的);但是,如果您计划在UI中向用户显示它,那么它是值得存储的。

最后,通常没有理由在脚本末尾调用MongoClient::close()。文档甚至建议不要这样做,因为它会削弱驱动程序管理持久连接的能力。

最新更新