package main import ( "image" "image/gif" "log" "net/http" "os" "regexp" "strconv" "github.com/chai2010/webp" "github.com/disintegration/imaging" ) // 实现一个 web api 服务(获取指定尺寸的图片) func main() { http.HandleFunc("/img/", func(w http.ResponseWriter, r *http.Request) { // URL 格式: /img/{id}-{version}@{倍图}{宽度}.{格式} reg := regexp.MustCompile(`^/img/([0-9a-zA-Z]+)-([0-9a-zA-Z]+)@([0-9]{1,4})x([0-9]{1,4}).(jpg|jpeg|png|webp)$`) matches := reg.FindStringSubmatch(r.URL.Path) if len(matches) != 6 { log.Println("URL 格式错误", matches) w.WriteHeader(http.StatusBadRequest) return } // 正则表达式获取参数 id, version, multiple_str, width_str, format := matches[1], matches[2], matches[3], matches[4], matches[5] multiple, err := strconv.Atoi(multiple_str) if err != nil { log.Println("倍图参数错误", multiple_str) w.WriteHeader(http.StatusBadRequest) return } width, err := strconv.Atoi(width_str) if err != nil { log.Println("宽度参数错误", width_str) w.WriteHeader(http.StatusBadRequest) return } log.Println(id, version, multiple, width, format) // 打開輸入文件 file, err := os.Open("data/test.gif") if err != nil { log.Println("打开文件失败", err) w.WriteHeader(http.StatusBadRequest) return } defer file.Close() // 將輸入文件解碼為 image.Image img, ext, err := image.Decode(file) if err != nil { log.Println("解码图像失败", err) w.WriteHeader(http.StatusBadRequest) return } // 如果是 GIF 格式的动态图片,直接返回 if ext == "gif" { giffile, err := os.Open("data/test.gif") if err != nil { log.Println("打开文件失败", err) w.WriteHeader(http.StatusBadRequest) return } defer giffile.Close() gifimg, err := gif.DecodeAll(giffile) if err != nil { log.Println("解码图像失败", err) w.WriteHeader(http.StatusBadRequest) return } gif.EncodeAll(w, gifimg) return } // 將圖像轉換為 RGBA 格式(如果尚未採用該格式) if _, ok := img.(*image.RGBA); !ok { img = imaging.Clone(img) } // 將圖像調整為指定宽度的 WebP 格式並將其寫入輸出到瀏覽器(高度自适应) if err = webp.Encode(w, imaging.Resize(img, multiple*width, 0, imaging.Lanczos), &webp.Options{Quality: 80}); err != nil { log.Println("编码图像失败", err.Error()) w.WriteHeader(http.StatusBadRequest) return } }) log.Println("Server is running at http://localhost:6001") http.ListenAndServe(":6001", nil) }