diff --git a/.gitignore b/.gitignore index f36c53a..06b5340 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ vendor/ .idea/ +cache/ \ No newline at end of file diff --git a/main.go b/main.go index 6959ba0..528236f 100644 --- a/main.go +++ b/main.go @@ -1,48 +1,113 @@ package main import ( + "crypto/md5" "fmt" "golang.org/x/image/webp" "image/jpeg" "io" "log" + "net/http" "os" + "strings" "time" ) func main() { - var ( - inFile io.Reader - outFile io.Writer - ) + _, err := os.Stat("cache") + if err == nil { + err := os.RemoveAll("cache") + if err != nil { + log.Fatal(err) + } + } + err = os.Mkdir("cache", os.ModeDir|os.ModePerm) + if err != nil { + log.Fatal(err) + } - iFile, err := os.OpenFile("/home/debuggerx/Pictures/test.webp", os.O_RDONLY, 0) + http.HandleFunc("/", wepb2jpgHandler) + err = http.ListenAndServe(":9999", nil) if err != nil { log.Fatal(err) } - defer iFile.Close() - inFile = iFile +} + +func hitCache(md5Path string, writer http.ResponseWriter) bool { + startTime := time.Now().UnixNano() + _, err := os.Stat("cache/" + md5Path) + if err != nil { + return false + } - oFile, err := os.OpenFile("/home/debuggerx/Pictures/test.jpg", os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.FileMode(0644)) + file, err := os.OpenFile("cache/"+md5Path, os.O_RDONLY, os.FileMode(0644)) + defer file.Close() if err != nil { log.Fatal(err) } - defer oFile.Close() - outFile = oFile + header := writer.Header() + header.Set("Access-Control-Allow-Origin", "*") + header.Set("content-type", "image/jpeg") + + if _, err := io.Copy(writer, file); err != nil { + log.Fatal(err) + } + endTime := time.Now().UnixNano() + fmt.Printf("命中缓存:%dμs\n", (endTime-startTime)/1e3) + + return true +} + +func wepb2jpg(path string, md5Path string, writer http.ResponseWriter) { startTime := time.Now().UnixNano() - m, err := webp.Decode(inFile) + + resp, getErr := http.Get(path) + if getErr != nil { + log.Fatal(getErr) + } endTime := time.Now().UnixNano() - fmt.Println((endTime - startTime) / 1e6) + + fmt.Printf("下载耗时:%dms\n", (endTime-startTime)/1e6) + + startTime = time.Now().UnixNano() + m, err := webp.Decode(resp.Body) if err != nil { log.Fatal(err) } + endTime = time.Now().UnixNano() + fmt.Printf("解码耗时:%dms\n", (endTime-startTime)/1e6) + + header := writer.Header() + header.Set("Access-Control-Allow-Origin", "*") + header.Set("content-type", "image/jpeg") + file, err := os.OpenFile("cache/"+md5Path, os.O_CREATE|os.O_WRONLY, os.FileMode(0644)) + defer file.Close() + if err != nil { + log.Fatal(err) + } startTime = time.Now().UnixNano() - err = jpeg.Encode(outFile, m, &jpeg.Options{Quality: 50}) - endTime = time.Now().UnixNano() - fmt.Println((endTime - startTime) / 1e6) + err = jpeg.Encode(io.MultiWriter(writer, file), m, &jpeg.Options{Quality: 50}) if err != nil { log.Fatal(err) } + endTime = time.Now().UnixNano() + fmt.Printf("编码耗时:%dms\n", (endTime-startTime)/1e6) +} + +func wepb2jpgHandler(writer http.ResponseWriter, request *http.Request) { + if !(strings.HasPrefix(request.URL.RawQuery, "http") && strings.HasSuffix(request.URL.RawQuery, ".webp")) { + writer.WriteHeader(404) + return + } + + m := md5.Sum([]byte(request.URL.RawQuery)) + md5Path := fmt.Sprintf("%x", m) + + if hitCache(md5Path, writer) { + return + } + + wepb2jpg(request.URL.RawQuery, md5Path, writer) }