|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/md5"
|
|
|
|
"fmt"
|
|
|
|
"golang.org/x/image/webp"
|
|
|
|
"image/jpeg"
|
|
|
|
"io"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
_, 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)
|
|
|
|
}
|
|
|
|
|
|
|
|
http.HandleFunc("/", webp2jpgHandler)
|
|
|
|
err = http.ListenAndServe(":9999", nil)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func hitCache(md5Path string, writer http.ResponseWriter) bool {
|
|
|
|
startTime := time.Now().UnixNano()
|
|
|
|
_, err := os.Stat("cache/" + md5Path)
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
file, err := os.OpenFile("cache/"+md5Path, os.O_RDONLY, os.FileMode(0644))
|
|
|
|
defer file.Close()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
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 webp2jpg(path string, md5Path string, writer http.ResponseWriter) {
|
|
|
|
startTime := time.Now().UnixNano()
|
|
|
|
|
|
|
|
resp, getErr := http.Get(path)
|
|
|
|
if getErr != nil {
|
|
|
|
log.Print(getErr)
|
|
|
|
writer.WriteHeader(404)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
endTime := time.Now().UnixNano()
|
|
|
|
|
|
|
|
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(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 webp2jpgHandler(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
|
|
|
|
}
|
|
|
|
|
|
|
|
webp2jpg(request.URL.RawQuery, md5Path, writer)
|
|
|
|
}
|