├── README.md ├── config.go ├── config.json ├── file.go ├── handle.go └── main.go /README.md: -------------------------------------------------------------------------------- 1 | # Quick Image Server 2 | 3 | ## 简介 4 | Quick Image Server是一个简单易用的图像服务器,目前支持JPEG格式。 5 | 6 | ## 配置文件 7 | 8 | ```JSON 9 | { 10 | "ListenAddr":":8086", <-监听地址 11 | "Storage":"/var/www/html/image/storage/" <-存储位置 12 | } 13 | ``` 14 | 15 | ## 使用方法 16 | ### 上传图片 17 | POST / 18 | 表单参数: 19 | uploadfile file类型,要上传的图片 20 | 返回值: 21 | {图片ID} 22 | 23 | ### 下载图片 24 | GET /{图片ID} 25 | 返回值: 26 | {图片文件} -------------------------------------------------------------------------------- /config.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "log" 6 | "os" 7 | ) 8 | 9 | type Config struct { 10 | ListenAddr string 11 | Storage string 12 | } 13 | 14 | var conf Config 15 | 16 | func LoadConf(){ 17 | r, err := os.Open("config.json") 18 | if err != nil { 19 | log.Fatalln(err) 20 | } 21 | decoder := json.NewDecoder(r) 22 | err = decoder.Decode(&conf) 23 | if err != nil { 24 | log.Fatalln(err) 25 | } 26 | } -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "ListenAddr":"0.0.0.0:10086", 3 | "Storage":"/var/www/html/image/storage" 4 | } -------------------------------------------------------------------------------- /file.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "github.com/seehuhn/mt19937" 5 | "time" 6 | "encoding/binary" 7 | "encoding/hex" 8 | "strings" 9 | "fmt" 10 | "os" 11 | ) 12 | 13 | func ImageID2Path(imageid string)string{ 14 | return fmt.Sprintf("%s/%s/%s/%s/%s/%s/%s/%s/%s.jpg",conf.Storage,imageid[0:2],imageid[2:4],imageid[4:6],imageid[6:8],imageid[8:10],imageid[10:12],imageid[12:14],imageid[14:16]) 15 | } 16 | 17 | func MakeImageID()string{ 18 | mt:=mt19937.New() 19 | mt.Seed(time.Now().UnixNano()) 20 | var buf = make([]byte, 8) 21 | binary.BigEndian.PutUint64(buf, mt.Uint64()) 22 | return strings.ToUpper(hex.EncodeToString(buf)) 23 | } 24 | 25 | func FileExist(filename string)bool{ 26 | if _, err := os.Stat(filename); err != nil { 27 | return false 28 | }else{ 29 | return true 30 | } 31 | } 32 | 33 | func BuildTree(imageid string)error{ 34 | return os.MkdirAll(fmt.Sprintf("%s/%s/%s/%s/%s/%s/%s/%s",conf.Storage,imageid[0:2],imageid[2:4],imageid[4:6],imageid[6:8],imageid[8:10],imageid[10:12],imageid[12:14]),0666) 35 | } -------------------------------------------------------------------------------- /handle.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gorilla/mux" 5 | "net/http" 6 | "os" 7 | "io" 8 | "log" 9 | ) 10 | 11 | func UploadHandler(w http.ResponseWriter, r *http.Request) { 12 | //随机生成一个不存在的fileid 13 | var imgid string 14 | for{ 15 | imgid=MakeImageID() 16 | if !FileExist(ImageID2Path(imgid)){ 17 | break 18 | } 19 | } 20 | //上传参数为uploadfile 21 | r.ParseMultipartForm(32 << 20) 22 | file, _, err := r.FormFile("uploadfile") 23 | if err != nil { 24 | log.Println(err) 25 | w.Write([]byte("Error:Upload Error.")) 26 | return 27 | } 28 | defer file.Close() 29 | //检测文件类型 30 | buff := make([]byte, 512) 31 | _, err = file.Read(buff) 32 | if err != nil { 33 | log.Println(err) 34 | w.Write([]byte("Error:Upload Error.")) 35 | return 36 | } 37 | filetype := http.DetectContentType(buff) 38 | if filetype!="image/jpeg"{ 39 | w.Write([]byte("Error:Not JPEG.")) 40 | return 41 | } 42 | //回绕文件指针 43 | log.Println(filetype) 44 | if _, err = file.Seek(0, 0); err!=nil{ 45 | log.Println(err) 46 | } 47 | //提前创建整棵存储树 48 | if err=BuildTree(imgid); err!=nil{ 49 | log.Println(err) 50 | } 51 | //log.Println(ImageID2Path(imgid)) 52 | f, err := os.OpenFile(ImageID2Path(imgid), os.O_WRONLY|os.O_CREATE, 0666) 53 | if err != nil { 54 | log.Println(err) 55 | w.Write([]byte("Error:Save Error.")) 56 | return 57 | } 58 | defer f.Close() 59 | io.Copy(f, file) 60 | w.Write([]byte(imgid)) 61 | } 62 | 63 | func DownloadHandler(w http.ResponseWriter, r *http.Request) { 64 | vars := mux.Vars(r) 65 | imageid := vars["imgid"] 66 | if len([]rune(imageid)) != 16 { 67 | w.Write([]byte("Error:ImageID incorrect.")) 68 | return 69 | } 70 | imgpath := ImageID2Path(imageid) 71 | if !FileExist(imgpath) { 72 | w.Write([]byte("Error:Image Not Found.")) 73 | return 74 | } 75 | http.ServeFile(w, r, imgpath) 76 | } 77 | 78 | func HomeHandler(w http.ResponseWriter, r *http.Request) { 79 | w.Write([]byte("

It Works!


Quick Image Server
")) 80 | } 81 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "fmt" 5 | "net/http" 6 | "log" 7 | "github.com/gorilla/mux" 8 | ) 9 | 10 | func main(){ 11 | fmt.Println("Quick Image Server.") 12 | fmt.Println("Author:zjyl1994@outlook.com.") 13 | LoadConf() 14 | r := mux.NewRouter() 15 | r.HandleFunc("/", HomeHandler).Methods("GET") 16 | r.HandleFunc("/",UploadHandler).Methods("POST") 17 | r.HandleFunc("/{imgid}",DownloadHandler).Methods("GET") 18 | err := http.ListenAndServe(conf.ListenAddr, r) 19 | if err != nil { 20 | log.Fatal("ListenAndServe error: ", err) 21 | } 22 | } 23 | --------------------------------------------------------------------------------