云计算开发者社区

用新浪微博连接

一步搞定

查看: 37622|回复: 44

SAE Storage文件管理器 [复制链接]

Rank: 7Rank: 7Rank: 7

发表于 2014-4-25 15:13:08 |显示全部楼层
本帖最后由 夏露Luke 于 2014-5-28 13:41 编辑

由于最近在写微信公众平台的项目。为了图方便,服务就丢到了SAE上面。
项目中有涉及资源【音乐、图片、视频……】的利用与管理。我们知道代码库的大小有限,同时读写非常严格,因此将文件丢到storage很有必要。
文件的管理是可以通过Storage管理的,但是管理起来多有不便,因此一个定制化的SAE Storage控制台很有必要。


就功能方面,既然是文件管理,那么文件的读、写是必要的功能。细化下来可以分为以下几个方面:
1,文件展示;
2,文件上传;
3,文件管理(主要是删除);


一步步来:
文件展示:
<?php 
header("Content-Type:text/html;charset='utf-8'");
class GetFiles{
    public $domain;
    public $prefix;
    public $limit;
    public $offset;
    static $allow_ext = array(
      'image' => array('gif', 'jpg', 'jpeg', 'png', 'bmp', 'psd'),
      'flash' => array('swf', 'flv'),
      'media' => array('mp3', 'wav', 'wma', 'wmv', 'mid', 'avi', 'mpg', 'asf', 'rm', 'rmvb'),
      'file' => array('pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'htm', 'html', 'txt', 'zip', 'rar', 'gz', 'bz2'),
    );//容许的文件扩展名
    
    public function __construct($domain,$offset='0',$limit='10',$prefix=''){
      $this->stor = new SaeStorage();
      $this->domain = $domain;
      $this->prefix = $prefix;
      $this->limit = $limit;
      $this->offset = $offset;
      $this->allow_ext = self::$allow_ext;
    }
    
    public function fileList(){
      $ret = $this->stor->getList($this->domain,$this->prefix,$this->limit,$this->offset);
      $fileInfo = null;
      for($i=0;$i<count($ret);$i++){
        if(substr($ret[$i],"-".strlen('/.placeholder'))!='/.placeholder'){
            $file_ext = strtolower(trim(array_pop(explode(".", $ret[$i]))));
            if(in_array($file_ext,$this->allow_ext['image'])===true){
              $format = 'image';
            }else if(in_array($file_ext,$this->allow_ext['flash'])===true){
              $format = 'flash';
            }else if(in_array($file_ext,$this->allow_ext['media'])===true){
              $format = 'media';
            }else if(in_array($file_ext,$this->allow_ext['file'])===true){
              $format = 'file';
            }else{
              $format = 'unknown';
            }
            
            $baseInfo = $this->stor->getAttr($this->domain , $ret[$i]);
            $fileInfo[$i]['file_ext'] = $file_ext;
            $fileInfo[$i]['format'] = $format;
            $fileInfo[$i]['content_type'] = $baseInfo['content_type'];
            $fileInfo[$i]['domain'] = $this->domain;
            $fileInfo[$i]['filename'] = $baseInfo['fileName'];
            $fileInfo[$i]['url'] = $this->stor->getUrl($this->domain , $ret[$i]);
            $fileInfo[$i]['length'] = $baseInfo['length'];
            $fileInfo[$i]['datetime'] = date("Y-M-d H:i:s",$baseInfo['datetime']);
            $fileInfo[$i]['md5sum'] = $baseInfo['md5sum'];
            $fileInfo[$i]['expires'] = $baseInfo['expires'];
        }
      }
      return json_encode($fileInfo);//返回一个json数据,方便处理
    }
}
$gf = new GetFiles('test');
echo $gf->fileList();
文件删除
<?php 
header("Content-Type:text/html;charset='utf-8'");
class DeleteFile{
    public $domain;
    public $filename;
    
    public function __construct($domain,$filename){
      $this->stor = new SaeStorage();
      $this->domain = $domain;
      $this->filename = $filename;
    }
    
    public function deleteSingle(){
      if($this->stor->fileExists($this->domain,$this->filename)===true){
        if($this->stor->delete($this->domain,$this->filename)===true){
            $this->alert(0,"File Deleted Success");
        }else{
            $this->alert(1,"Failed to Delete File");
        }
      }else{
        $this->alert(1,"No such file");
      }
    }
    
//封装一个提醒类,方便ajax处理
    public function alert($errorFlag,$msgContent){
      $callback = array('errorFlag' => $errorFlag, 'msgContent' => $msgContent);
      $alertInfo = json_encode($callback);
      echo $alertInfo;
      exit;
    }
}

$domain = $_GET['domain'];
$filename = $_GET['filename'];
$df = new DeleteFile($domain,$filename);
$df->deleteSingle();
文件上传表单
<!Doctype html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8" />
    <title>My Resume</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<form action="mail.php" method="post">
    <input type="type" name="toUser" placeholder="请输入邮箱地址" /><br />
  <input type="type" name="title" placeholder="请输入邮件标题" /><br />
    <textarea name="content">请输入邮件标题</textarea><br />
  <input type="submit" value="Send Mail" />
</form>
</body>
</html>

文件上传处理

<?php 
$domain="test";
$file_name = $_FILES["imgFile"]["name"];
$allow_ext = array(
    'image' => array('gif', 'jpg', 'jpeg', 'png', 'bmp'),
    'flash' => array('swf', 'flv'),
    'media' => array('swf', 'flv', 'mp3', 'wav', 'wma', 'wmv', 'mid', 'avi', 'mpg', 'asf', 'rm', 'rmvb'),
    'file' => array('doc', 'docx', 'xls', 'xlsx', 'ppt', 'htm', 'html', 'txt', 'zip', 'rar', 'gz', 'bz2'),
);//容许的文件扩展名
$file_ext = strtolower(trim(array_pop(explode(".", $file_name))));
$dir_name = empty($_GET['dir'])?'image':trim($_GET['dir']);
if(in_array($file_ext,$allow_ext[$dir_name])===false){
  alert("不支持的扩展名,目前我们仅支持以下扩展名:".implode(',',$allow_ext[$dir_name]));
  exit;
}
$new_file_name = 'image/'.date("Ymd") . '/' .time().'.'.$file_ext;
$s = new SaeStorage();
//$s->upload( 'imagefile',$_FILES["myfile"]["name"],$_FILES["myfile"]["name"]);
$aimage=$s->upload( 'test',$new_file_name,$_FILES["imgFile"]["tmp_name"]);
echo "<img src='".$aimage."' />";

function alert($msg) {
    header('Content-type: text/html; charset=UTF-8');
    var_dump(array('error' => 1, 'message' => $msg));
    exit;
}
代码主要是逻辑核心,展现层面没有挂上来,在完善之后基友们可以到我的github围观。
这份代码将上传到我的github,项目地址为https://github.com/xialu/SAE-Storage-SDK ,欢迎光临

使用道具 举报

Rank: 9Rank: 9Rank: 9

发表于 2014-4-25 18:18:41 |显示全部楼层
感谢分享,这个很厉害啊!

使用道具 举报

Rank: 7Rank: 7Rank: 7

发表于 2014-4-25 21:36:22 |显示全部楼层
白天将Storage文件管理器的后端逻辑处理得差不多了,虽说代码很多地方可以优化,但是还算是可以使用。
这里,继续完善文件管理器。本次回复主要是针对展现层的说明。
由于发帖的核心轻美工(主要由于前端方面的东西都比较简单,而且多样化更多),所以这里采用了一套现成的后台模板来完成有关工作。

后台模板来自老外,下载、Demo地址为http://www.prepbootstrap.com/bootstrap-theme/lightway-admin

这里我贴出我做出的效果展示:
文件列表


图片预览


影音播放


由于不是重点,因此这里只提几点技术要点。
1,整个展现的前端框架是bootstrap,用到了table、model
2,文件列表拉取自文档帖子中的所有文件列表的代码,写入到展现文件可以加载json数据或者load出数据数据,看个人喜好;
3,影音文件的预览由于html5兼容性不太好,所以这里可以使用一些比较成熟的swf解决方案--dewplayer,图了个简单,我采用了html5;

核心代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>SAE控制台</title>
  <link rel="stylesheet" type="text/css" href="bootstrap/css/bootstrap.min.css" />
  <link rel="stylesheet" type="text/css" href="font-awesome/css/font-awesome.min.css" />
  <link rel="stylesheet" type="text/css" href="css/local.css" />
  <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
  <script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
  <script type="text/javascript">
  $(document).on("click",".open-Modal",function(){
    var myModalSrc = $(this).data('url');
    $(".modal-body #imgSrc").attr('src',myModalSrc);
  });
  
  $(document).on("click",".open-musicModal",function(){
    var musicModalSrc = $(this).data('url');
    $(".modal-body #mp3value").attr('src',musicModalSrc);
  });
  
  function clsVideo(){
    $("#mp3value").pause();
  }
  </script>
</head>
<body>
  <div id="wrapper">
    <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">    
    <div class="navbar-header">
      <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="index.html">仪表盘</a>
    </div>
    <div class="collapse navbar-collapse navbar-ex1-collapse">
      <ul class="nav navbar-nav side-nav">
        <li><a href="index.php"><i class="fa fa-bullseye"></i> 控制面板</a></li>
          <li class="active"><a href="storage.php"><i class="fa fa-file-o"></i> Storage</a></li>
        <li><a href="portfolio.php"><i class="fa fa-tasks"></i> 相册</a></li>
        <li><a href="blog.php"><i class="fa fa-globe"></i> Blog</a></li>
        <li><a href="forms.php"><i class="fa fa-list-ol"></i> 表单</a></li>
        <li><a href="typography.php"><i class="fa fa-font"></i> 段落</a></li>
        <li><a href="bootstrap-elements.php"><i class="fa fa-list-ul"></i> BS Elements </a></li>
        <li><a href="bootstrap-grid.php"><i class="fa fa-table"></i > BS Grid</a></li>        
      </ul>
      <ul class="nav navbar-nav navbar-right navbar-user">
        <li class="dropdown messages-dropdown">
        <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-envelope"></i> 通知 <span class="badge">2</span> <b class="caret"></b></a>
        <ul class="dropdown-menu">
          <li class="dropdown-header">2 条新消息</li>
          <li class="message-preview">
            <a href="#">
            <span class="avatar"><i class="fa fa-bell"></i></span>
            <span class="message">Security alert</span>
            </a>
          </li>
          <li class="divider"></li>
          <li class="message-preview">
            <a href="#">
            <span class="avatar"><i class="fa fa-bell"></i></span>
            <span class="message">Security alert</span>
            </a>
          </li>
          <li class="divider"></li>
          <li><a href="#">消息中心 <span class="badge">2</span></a></li>
        </ul>
        </li>
        <li class="dropdown user-dropdown">
        <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-user"></i> Luke<b class="caret"></b></a>
        <ul class="dropdown-menu">
          <li><a href="#"><i class="fa fa-user"></i> 个人资料</a></li>
          <li><a href="#"><i class="fa fa-gear"></i> 设置</a></li>
          <li class="divider"></li>
          <li><a href="#"><i class="fa fa-power-off"></i> 退出</a></li>
        </ul>
      </li>
      </ul>
    </div>
    </nav>

    <div id="page-wrapper">
    <div class="row">
      <div class="col-lg-12">
        <div class="panel panel-primary">
        <div class="panel-heading">
          <h3 class="panel-title"><i class="fa fa-bar-chart-o"></i> 文件列表</h3>
        </div>
        <div class="panel-body">
          <div id="shieldui-grid1">
                <table width="100%" class="table table-bordered table-hover">
                  <thead>
                    <tr>
                      <th>扩展名</th>
                      <th>类型</th>
                      <!-- th>格式</th>
                      <th>Domain</th -->
                      <th>文件名</th>
                      <th>大小</th>
                      <th>创建时间</th>
                      <!-- th>到期时间</th>
                      <th>Md5Sum</th -->
                      <th>操作</th>
                    </tr>
                  </thead>
                  <tbody>
                    <?php 
                      $json = file_get_contents("http://8.xialu.sinaapp.com/FileManager/getfiles.php");
                      $array = json_decode($json,true);
                      for($i=0;$i<count($array);$i++){
                    ?>
                    <tr>
                      <td><?php echo $array[$i]['file_ext']; ?></td>
                      <td><?php echo $array[$i]['format']; ?></td>
                      <!-- td><?php echo $array[$i]['content_type']; ?></td>
                      <td><?php echo $array[$i]['domain']; ?></td -->
                      <td><?php echo $array[$i]['filename']; ?></td>
                      <td><?php echo $array[$i]['length']; ?></td>
                      <td><?php echo $array[$i]['datetime']; ?></td>
                      <!-- td><?php echo $array[$i]['expires']; ?></td>
                      <td><?php echo $array[$i]['md5sum']; ?></td -->
                      <td>
                        <?php if($array[$i]['format']=='image'){ ?>
                        <button class="btn btn-default btn-xs open-Modal" data-toggle="modal" data-target="#myModal" data-url="<?php echo $array[$i]['url']; ?>">预览</button>
                        <?php }else if($array[$i]['format']=='media'){ ?>
                        <button class="btn btn-default btn-xs open-musicModal" data-toggle="modal" data-target="#musicModal" data-url="<?php echo $array[$i]['url']; ?>">影音</button>
                        <?php }else{ ?>
                        <a class="btn btn-default btn-xs" href="<?php echo $array[$i]['url']; ?>" target="_blank" >下载</button>
                        <?php } ?>
                        <a class="btn btn-danger btn-xs" href="<?php echo $array[$i]['url']; ?>" target="_blank" >删除</a>
                      </td>
                      <!-- td><?php echo "<a href='".$array[$i]['url']."' target='_blank' >预览</a>"; ?></td-->
                    </tr>
                    <?php 
                      }
                    ?>
                  </tbody>
                </table>
                <ul class="pagination">
                  <li><a href="storage.php">«</a></li>
                  <li><a href="storage.php">1</a></li>
                  <li><a href="storage.php?page=2">2</a></li>
                  <li><a href="storage.php?page=3">3</a></li>
                  <li><a href="storage.php?page=4">4</a></li>
                  <li><a href="storage.php?page=5">5</a></li>
                  <li><a href="storage.php?page=2">»</a></li>
                </ul>
              </div>
        </div>
        </div>
      </div>
    </div>
    <!-- /.row -->
    </div>
    <!-- /#page-wrapper -->
  </div>
  <!-- /#wrapper -->
  
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog">
  <div class="modal-content">
  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    <h4 class="modal-title" id="myModalLabel">Modal title</h4>
  </div>
  <div class="modal-body">
    <img src="" id="imgSrc" style="max-width:560px" />
  </div>
  <div class="modal-footer">
    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
    <button type="button" class="btn btn-primary" data-dismiss="modal">See you</button>
  </div>
  </div><!-- /.modal-content -->
  </div><!-- /.modal-dialog -->
</div><!-- /.modal -->

<div class="modal fade" id="musicModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog">
  <div class="modal-content">
  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    <h4 class="modal-title" id="myModalLabel">Modal title</h4>
  </div>
  <div class="modal-body">
    <video src="" id="mp3value" controls="controls" style="width:560px">
      基友,你该换浏览器了
    </video>
  </div>
  <div class="modal-footer">
    <button type="button" class="btn btn-default" data-dismiss="modal" onclick="clsVideo()">Close</button>
    <button type="button" class="btn btn-primary" data-dismiss="modal">See you</button>
  </div>
  </div><!-- /.modal-content -->
  </div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</body>
</html>



附件: 你需要登录才可以下载或查看附件。没有帐号?立即注册

点评

通人性的驴  很强悍  发表于 2015-1-19 11:37:20

使用道具 举报

Rank: 9Rank: 9Rank: 9

发表于 2014-4-25 23:56:39 |显示全部楼层
文件上传表单 是 发邮件表单 吧

使用道具 举报

Rank: 7Rank: 7Rank: 7

发表于 2014-4-26 03:28:51 |显示全部楼层
-圣使- 发表于 2014-4-25 23:56
文件上传表单 是 发邮件表单 吧

十分抱歉,由于个人疏附,之前的文件上传表单有错误(贴成了邮件发送表单)!这里给出一份正确的文件上传表单如下↓
<!Doctype html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8" />
    <title>My Resume</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="JqueryMobile/jquery.mobile-1.4.2.min.css" />
    <script src="JqueryMobile/demos/js/jquery.js"></script>
    <script src="JqueryMobile/jquery.mobile-1.4.2.min.js"></script>
</head>
<body>
<form enctype="multipart/form-data" action="upload2.php" method="POST">
  <!-- MAX_FILE_SIZE must precede the file input field -->
  <input type="hidden" name="MAX_FILE_SIZE" value="1024000000" />
  <!-- Name of input element determines name in $_FILES array -->
  Send this file: <input name="imgFile" type="file" />
  <input type="submit" value="Send File" />
</form>
</body>
</html>
感谢上楼-圣使-的提醒!




使用道具 举报

Rank: 2

发表于 2014-4-26 10:33:20 |显示全部楼层
人工置顶~~感谢分享!!学习学习
dehao博客←求交换友链
网页版2048←我已经2048了!你呢?
@Rdquo陈德豪

使用道具 举报

Rank: 1

发表于 2014-4-26 12:38:07 |显示全部楼层
32个赞!必须加精,对小白如我,来说是学习不可多得的范例。

正好也需要开发个这样的东东,边学边用了

使用道具 举报

Rank: 2

发表于 2014-4-27 00:13:45 |显示全部楼层
谢谢分享.....
微笑是最俱亲和力的沟通

使用道具 举报

Rank: 7Rank: 7Rank: 7

发表于 2014-4-28 15:29:02 |显示全部楼层
一个周末过去了,眼看帖子快要沉了,火速来一发,将主要功能已完善的代码贴成附件发上来。


顺道,将整个项目的界面截图如下:
1,列表页面


2,预览页面


3,上传表单


4,上传成功


5,删除文件
↓删除成功


↓没有对应文件-删除失败


6,顺便给个代码目录
J:\Projects\Web\xialu.sinaapp.com\8\FileManager>tree
Folder PATH listing for volume Lacie Code
Volume serial number is 00000200 36C9\"\"54A
J:.
├─bootstrap
│  ├─css
│  ├─fonts
│  └─js
├─css
├─font-awesome
│  ├─css
│  ├─fonts
│  ├─less
│  └─scss
├─js
│  ├─js
│  │  ├─i18n
│  │  └─minified
│  └─plugins
  ├─bootstrap
  │  ├─css
  │  ├─fonts
  │  └─js
  ├─css
  ├─font-awesome
  │  ├─css
  │  ├─fonts
  │  ├─less
  │  └─scss
  └─js
备注:
1,由于SAE Storage目前没有文件夹的说法(详细看Storage的API),所以文件名都是带着路径的
2,由于代码是在上班时间开小差写的,时间比较赶,所以难免会比较难看,但凡有不明了的,还请留言本帖或者微博私信/评论;
3,项目到这里快接近尾声了,剩下的是功能的添加--登录权限控制、用户管理;
4,这个帖子到这里算是Over了,以后本贴子将不再更新,代码也放上来了,责任完成啦;
5,帖子不更新,但是代码会跟进,更新的代码还请移步我的GitHub:::  https://github.com/xialu/SAE-Storage-SDK
6,代码可以随意复制粘贴、删减更改、发布使用、收费售卖……但是我这里copyleft;
7,使用过程当中如果有问题,请回复本帖或者微博联系(微博在左边头像下面)。
附件: 你需要登录才可以下载或查看附件。没有帐号?立即注册

使用道具 举报

Rank: 2

发表于 2014-5-6 13:59:08 |显示全部楼层
强烈支持楼主,给我等菜鸟带来了及时雨,简直就是公明在世啊。

使用道具 举报

Rank: 2

发表于 2014-5-13 19:58:39 |显示全部楼层
好贴   mark 下 部署到我哪玩玩!

使用道具 举报

Rank: 1

发表于 2014-5-16 23:30:15 |显示全部楼层
谢谢楼主分享!学习了!

使用道具 举报

Rank: 4

发表于 2014-5-23 14:10:44 |显示全部楼层
很不错,不过看页面里还有模板里面的示范代码和js,楼主肯定不是处女座的。。。

使用道具 举报

Rank: 7Rank: 7Rank: 7

发表于 2014-5-24 19:22:07 |显示全部楼层
TopFlowOA办公平台 发表于 2014-5-23 14:10
很不错,不过看页面里还有模板里面的示范代码和js,楼主肯定不是处女座的。。。 ...

你才是处女座~你全家都是处女座。
这些东西留下来方便看代码的继续开发思密达。

使用道具 举报

Rank: 1

发表于 2014-5-28 11:44:11 |显示全部楼层
这都不加精,版主太抠了。。。。。

使用道具 举报

Rank: 1

发表于 2014-6-5 15:17:00 |显示全部楼层
本帖最后由 宝罗森 于 2014-6-5 15:22 编辑
夏露Luke 发表于 2014-5-24 19:22
你才是处女座~你全家都是处女座。
这些东西留下来方便看代码的继续开发思密达。 ...
楼主君 请教微信生成mediaID问题: 图片放在storage上如何生成mediaID
我用curl模拟post请求 发送的数据结构我是这样的('media'=>'@http://kjdian-images.stor.sinaapp.com/1401943791.jpg'),但是这样总是请求失败 返回false;
如果我给的是物理路径('media'=>'@/data1/www/htdocs/792/yy/1/xx.jpg')就可以正确返回mediaID;
图片传到storage上用geturl或者upload方法 获得的都是这种HTTP://****.jpg的图片路由  有没有直接获得物理路径的方法?

使用道具 举报

Rank: 2

发表于 2014-6-20 11:33:06 |显示全部楼层
夏露Luke 发表于 2014-4-28 15:29
一个周末过去了,眼看帖子快要沉了,火速来一发,将主要功能已完善的代码贴成附件发上来。

好样的 马克

使用道具 举报

Rank: 4

发表于 2014-6-22 08:33:59 |显示全部楼层
谢谢楼主分享!

使用道具 举报

Rank: 1

发表于 2014-6-22 14:41:25 |显示全部楼层
楼主牛逼啊。。。。赞

使用道具 举报

Rank: 1

发表于 2014-7-2 15:27:46 |显示全部楼层
超赞

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

Archiver|云计算开发者社区 ( 京ICP证000007-137 )

GMT+8, 2018-7-21 19:52 , Processed in 0.337325 second(s), Total 16, Slave 15 queries .

Powered by Discuz! X2

© 2001-2011 Comsenz Inc.

回顶部