读书人

模块容易设计设计简单的存储系统

发布时间: 2012-12-28 10:29:05 作者: rapoo

模块简单设计——设计简单的存储系统

用下面用nginx+mongodb+php实现一个简单的存储系统,提供简单的文件上传下载功能(下载支持Range头)。

(后台用磁盘和mongo的gridfs分别存储大于1M和小于等于1M的文件)

?

A,前台文件上传页面(同时列举所有文件)(test.php)

<html><head>        <meta http-equiv="content-type" content="text/html;charset=utf-8" /></head><body><!--查询meta中所有文件-->        <ul>                <?php                        $mongo = new Mongo();                        $db = $mongo->selectDB("ciaos");                        $meta = $db->meta;                        $cursor = $meta->find();                        foreach ($cursor as $doc) {                                $filename = $doc["filename"];                                echo "<li><a href=\"dl/$filename\">$filename</a></li>";                        }                ?>        </ul>        <form enctype="multipart/form-data" action="upload.php" method="POST">        <!-- Name of input element determines name in $_FILES array -->                Send this file: <input name="Filedata" id="Filedata" type="file" />                <input name="submit" type="submit" value="Send File" />        </form></body></html>

B,服务器端文件上传(upload.php)

<?php// 存放文件的磁盘位置$targetFolder = '/files';if (!empty($_FILES)) {        //获取上传文件的临时文件,大小,设置存储路径        $tempFile = $_FILES['Filedata']['tmp_name'];        $size = $_FILES['Filedata']['size'];        $targetPath = $_SERVER['DOCUMENT_ROOT'] . $targetFolder;        $targetFile = rtrim($targetPath,'/') . '/' . $_FILES['Filedata']['name'];        $mongo = new Mongo();        $db = $mongo->selectDB("ciaos");        //大于1M的文件放在磁盘中,然后写meta信息        if($size > 1024*1024) {                move_uploaded_file($tempFile,$targetFile);                $newfile = array(                                "filename" => $_FILES['Filedata']['name'],                                "savename" => $targetFile,                                "size" => $size                        );        } else { //小文件存放在mongofs中,然后写meta                $gridfs = $db->getGridFS();                $mid = $gridfs->put($tempFile);                $newfile = array(                                "filename" => $_FILES['Filedata']['name'],                                "mid" => $mid,                                "size" => $size                        );        }        //meta中存储文件名信息,mongoID或者存储名称以及文件大小        $meta = $db->meta;        $meta->save($newfile);        echo "Upload succeed";}else {        echo "Upload failed";}exit();?>

C,文件下载逻辑(download.php)

<?php$file = isset($_GET["file"])?$_GET["file"]:NULL;if ($file) {        //去meta中查询文件信息        $mongo = new Mongo();        $db = $mongo->selectDB("ciaos");        $meta = $db->meta;        $search = array(                "filename"=>$file        );        $search_result = $meta->findOne($search);        $size=  $search_result["size"];        //如果文件大于1M,转到磁盘下载        if($size > 1024*1024) {                header("Content-type: application/octet-stream");                header("X-Accel-Redirect: /files/" . $file);        } else { //小文件则从mongofs中读取存放在临时文件中,然后转临时文件下载                $gridfs = $db->getGridFS();                $mid = $search_result["mid"];                $fsfile = $gridfs->get($mid);                $tmpname = "tmp".time();                file_put_contents("./files/$tmpname",$fsfile->getBytes());                header("Content-type: application/octet-stream");                header("X-Accel-Redirect: /files/" . $tmpname);        }}else {        echo "Invalid filename";}?>

D,数据库中存储小文件内容以及meta信息,查询结果分别如下

> db.fs.files.find(){ "_id" : ObjectId("50b5d1a892a5f27a0f000001"), "filename" : "/usr/local/NSP/var/php_upload_tmp/phpmgM6IS", "uploadDate" : ISODate("2012-11-28T08:56:08.480Z"), "length" : 13, "chunkSize" : 262144, "md5" : "d4369b7a8614277c011ef987ca4e16ee" }{ "_id" : ObjectId("50b5ddb592a5f2452f000001"), "filename" : "/usr/local/NSP/var/php_upload_tmp/php4hu6fi", "uploadDate" : ISODate("2012-11-28T09:47:33.094Z"), "length" : 13, "chunkSize" : 262144, "md5" : "d4369b7a8614277c011ef987ca4e16ee" }>
> db.meta.find(){ "_id" : ObjectId("50b5d8ca92a5f2b42d000000"), "filename" : "dbank-sdk-cpp-0.5.5.zip", "savename" : "/usr/local/NSP/htdocs/files/dbank-sdk-cpp-0.5.5.zip", "size" : 4380805 }{ "_id" : ObjectId("50b5ddb592a5f2452f000003"), "filename" : "测试.txt", "mid" : ObjectId("50b5ddb592a5f2452f000001"), "size" : 13 }>

E,nginx核心配置(nginx.conf)

location / {index  index.html index.htm index.php;rewrite ^/dl/(.*) /download.php?file=$1 last;}location /files {root /usr/local/ciaos/html/;internal;}location ~ .*\.php$ {fastcgi_index index.php;fastcgi_pass   unix:/usr/local/ciaos/php_fcgi.socket;include /usr/local/ciaos/fastcgi.conf;}

nginx的配置主要需要注意下面几点:

1,支持php服务器端脚本运行

2,配置下载目录/files,设置为internal内部访问,这样可以避免用户直接下载磁盘,可以自定义鉴权等功能

3,配置路径转发,前台的下载路径看起来就是这样http://localhost/dl/test.txt,后台通过download.php实现下载功能。

读书人网 >其他相关

热点推荐