package manager

import (
    "net/http"
    "regexp"
    "strconv"
    "io"
    "fmt"
    "github.com/030io/whalefs/manager/volume"
    "gopkg.in/redis.v2"
    "os"
)

var (
    postVolumeUrl *regexp.Regexp  //提交卷文件正则表达式
    postFileUrl *regexp.Regexp  //提交文件正则表达式
    deleteFileUrl  *regexp.Regexp  //删除文件url 正则表达式
)
//初始化文件表达式
func init() {
    var err error
    postVolumeUrl, err = regexp.Compile("/([0-9]*)/")
    if err != nil {
        panic(err)
    }

    postFileUrl, err = regexp.Compile("/([0-9]*)/([0-9]*)/(.*)")
    if err != nil {
        panic(err)
    }

    deleteFileUrl = postFileUrl
}

type Size interface {
    Size() int64
}
//文件管理处理器
func (vm *VolumeManager)adminEntry(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case http.MethodGet, http.MethodHead:
        vm.publicEntry(w, r)
    case http.MethodPost:
        if postFileUrl.MatchString(r.URL.Path) {
            vm.adminPostFile(w, r)
        } else if postVolumeUrl.MatchString(r.URL.Path) {
            vm.adminPostVolume(w, r)
        } else {
            http.Error(w, r.URL.String() + " can't match", http.StatusNotFound)
        }
    case http.MethodDelete:
        if deleteFileUrl.MatchString(r.URL.Path) {
            vm.adminDeleteFile(w, r)
        } else {
            http.Error(w, r.URL.String() + " can't match", http.StatusNotFound)
        }
    default:
        w.WriteHeader(http.StatusMethodNotAllowed)
    }
}
//卷文件管理处理器
func (vm *VolumeManager)adminPostVolume(w http.ResponseWriter, r *http.Request) {
    match := postVolumeUrl.FindStringSubmatch(r.URL.Path)
    vid, _ := strconv.ParseUint(match[1], 10, 64)
    volume, err := volume.NewVolume(vm.DataDir, vid)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    vm.Volumes[vid] = volume
    w.WriteHeader(http.StatusCreated)
}
//上传文件处理器
func (vm *VolumeManager)adminPostFile(w http.ResponseWriter, r *http.Request) {
    match := postFileUrl.FindStringSubmatch(r.URL.Path)
    vid, _ := strconv.ParseUint(match[1], 10, 64)
    volume, ok := vm.Volumes[vid]
    if !ok {
        http.Error(w, "can't find volume", http.StatusNotFound)
        return
    }
    file, header, err := r.FormFile("file")
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    defer file.Close()

    var fileSize int64
    switch file.(type) {
    case *os.File:
        s, _ := file.(*os.File).Stat()
        fileSize = s.Size()
    case Size:
        fileSize = file.(Size).Size()
    }
    fid, _ := strconv.ParseUint(match[2], 10, 64)
    file_, err := volume.NewFile(fid, header.Filename, uint64(fileSize))
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    defer func() {
        if err != nil {
            if err := volume.Delete(file_.Info.Fid, file_.Info.FileName); err != nil {
                panic(err)
            }
        }
    }()

    n, err := io.Copy(file_, file)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    } else if n != fileSize {
        err = fmt.Errorf("%d != %d", n, fileSize)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    w.WriteHeader(http.StatusCreated)
}
//文件删除
func (vm *VolumeManager)adminDeleteFile(w http.ResponseWriter, r *http.Request) {
    match := deleteFileUrl.FindStringSubmatch(r.URL.Path)
    vid, _ := strconv.ParseUint(match[1], 10, 64)
    volume := vm.Volumes[vid]
    if volume == nil {
        http.Error(w, "can't find volume", http.StatusNotFound)
        return
    }

    fid, _ := strconv.ParseUint(match[2], 10, 64)
    err := volume.Delete(fid, match[3])
    if err == redis.Nil {
        http.NotFound(w, r)
    } else if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    } else {
        w.WriteHeader(http.StatusAccepted)
    }
}

admin-handlers.go的更多相关文章

  1. Solr Cloud - SolrCloud

    关于 Solr Cloud Zookeeper 入门,介绍 原理 原封不动转自 http://wiki.apache.org/solr/SolrCloud/ ,文章的内存有些过时,但是了解原理. Th ...

  2. Ansible6:Playbook简单使用【转】

    ansbile-playbook是一系列ansible命令的集合,利用yaml 语言编写.playbook命令根据自上而下的顺序依次执行.同时,playbook开创了很多特性,它可以允许你传输某个命令 ...

  3. Importing/Indexing database (MySQL or SQL Server) in Solr using Data Import Handler--转载

    原文地址:https://gist.github.com/maxivak/3e3ee1fca32f3949f052 Install Solr download and install Solr fro ...

  4. $2015 武汉森果公司web后端开发实习日记----书写是为了更好的思考

    找暑期实习,3月份分别投了百度和腾讯的实习简历,都止步于笔试,总结的主要原因有两点:基础知识不扎实,缺乏项目经验.后来到拉勾网等网站上寻找实习,看了很多家,都还是处于观望状态.后来参加了武汉实习吧在大 ...

  5. ansible小结(八)ansible-playbook简单使用

    ansbile-playbook是一系统ansible命令的集合,其利用yaml 语言编写,运行过程,ansbile-playbook命令根据自上而下的顺序依次执行.同时,playbook开创了很多特 ...

  6. 【Django】--Models 和ORM以及admin配置

    Models 数据库的配置 1    django默认支持sqlite,mysql, oracle,postgresql数据库 <1>sqlite django默认使用sqlite的数据库 ...

  7. elmah - Error Logging Modules and Handlers for ASP.NET - 1 : 初体验

    elmah(英文):https://code.google.com/p/elmah/   写作思路:先看结果,然后再说原理   elmah文章基本内容如下   1.安装 2.基本使用 3.详细配置讲解 ...

  8. DoesNotExist at /admin/

    DoesNotExist at /admin/ User has no account. Request Method: GET Request URL: http://127.0.0.1:8000/ ...

  9. django 自己编写admin

    继上次CRM项目之后 我们发现了django自带admin的强大之处以及灵活性,但是admin在企业中也一样很难做到完全的对接,因此编写自己的后台管理就显得至关重要. 本次自定义admin项目将接着上 ...

  10. Django admin模块使用search时报错:django.core.exceptions.FieldError: Related Field got invalid lookup: contains

    日志如下: <class 'django.core.handlers.wsgi.WSGIRequest'> ------------registered_admins: {'spaceCl ...

随机推荐

  1. 熊猫猪新系统测试之四:Ubuntu 14.04

    目前猫猪在办公室一般用的就是乌班图系统,一方面原因是老本本性能跑不起来Windows,更重要的是本猫觉得Linux系统更开放些.况且现在用的也比较熟了,完全可以脱离Windows鸟!这一系列4篇新系统 ...

  2. C#编译器优化那点事

    使用C#编写程序,给最终用户的程序,是需要使用release配置的,而release配置和debug配置,有一个关键区别,就是release的编译器优化默认是启用的. 优化代码开关即optimize开 ...

  3. spring boot + quartz 集群

    spring boot bean配置: @Configuration public class QuartzConfig { @Value("${quartz.scheduler.insta ...

  4. objc/runtime.h 查看私有api

    objc/runtime.h 相关 Objecitve-C的重要特性是Runtime(运行时),在Interacting with the Runtime(交互运行)中,运行时函数部分,苹果给出了/u ...

  5. TCP / IP,HTTP

    大学学习网络基础的时候老师讲过,网络由下往上分为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层.通过初步的了解,我知道IP协议对应于网络层,TCP协议对应于传输层,而HTTP协议对应于应用 ...

  6. java设计模式--单列模式

    java设计模式--单列模式 单列模式定义:确保一个类只有一个实例,并提供一个全局访问点. 下面是几种实现单列模式的Demo,每个Demo都有自己的优缺点: Demo1: /** * 单列模式需要满足 ...

  7. hadoop 2.x安装:完全分布式安装

    1. 安装环境 本文使用三台CentOS6.4虚拟机模拟完全分布式环境.前五个过程和hadoop1.x安装相同 1.1. 安装环境 项目 参数 主操作系统 Windows 10 64 bit,8GB内 ...

  8. HttpDNS的坑以及一个针对安卓不太完善的测试方案

    背景:单位因为域名劫持(具体表象是某个地区的用户ping不通域名或者因为DNS解析的ip跨网段导致访问速度很慢)需要运维经常去定位,于是提出了httpDNS方案. 想法是美好的,现实是残酷的.没引入这 ...

  9. RDC去省赛玩前の日常训练 Chapter 2

    2018.4.9 施展FFT ing! 马上就要和前几天学的斯特林数双剑合璧了!

  10. python 脚本自动登陆校园网

    学校的校园网每次重开电脑时都要重新打开浏览器进行网页登录,繁琐的操作比较麻烦,于是便写了个python的脚本进行自动登录,下面说下具体的操作过程: 1. 方法说明 博主采用的python的 reque ...