package storage import ( "io" "net/http" "os" "strconv" "strings" ) func contentType2Ext(contentType string) string { if strings.Contains(contentType, "image/jpeg") { return "jpg" } else if strings.Contains(contentType, "audio/mpeg") { return "mp3" } else if strings.Contains(contentType, "video/mp4") { return "mp4" } return "" } func ext2ContentType(ext string) string { ext = strings.ToLower(ext) switch ext { // 图片格式 case "jpg", "jpeg": return "image/jpeg" case "png": return "image/png" case "gif": return "image/gif" case "webp": return "image/webp" case "bmp": return "image/bmp" case "svg", "svgz": return "image/svg+xml" case "ico": return "image/x-icon" case "tiff", "tif": return "image/tiff" case "avif": return "image/avif" case "apng": return "image/apng" // 音频格式 case "mp3": return "audio/mpeg" case "wav": return "audio/wav" case "ogg": return "audio/ogg" case "flac": return "audio/flac" case "aac": return "audio/aac" case "m4a": return "audio/mp4" // 视频格式 case "mp4": return "video/mp4" case "avi": return "video/x-msvideo" case "mov", "qt": return "video/quicktime" case "webm": return "video/webm" case "flv": return "video/x-flv" case "mkv": return "video/x-matroska" case "wmv": return "video/x-ms-wmv" case "m3u8": return "application/vnd.apple.mpegurl" case "ts": return "video/mp2t" // 文档格式 case "pdf": return "application/pdf" case "doc": return "application/msword" case "docx": return "application/vnd.openxmlformats-officedocument.wordprocessingml.document" case "xls": return "application/vnd.ms-excel" case "xlsx": return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" case "ppt": return "application/vnd.ms-powerpoint" case "pptx": return "application/vnd.openxmlformats-officedocument.presentationml.presentation" case "txt": return "text/plain" case "html", "htm": return "text/html" case "css": return "text/css" case "js": return "application/javascript" case "json": return "application/json" case "xml": return "application/xml" case "zip": return "application/zip" case "rar": return "application/x-rar-compressed" case "7z": return "application/x-7z-compressed" case "gz": return "application/gzip" default: return "" } } // detectContentType 从文件内容检测 MIME 类型 func detectContentType(filePath string) string { f, err := os.Open(filePath) if err != nil { return "" } defer f.Close() // 读取前 512 字节用于检测 buf := make([]byte, 512) n, err := f.Read(buf) if err != nil && err != io.EOF { return "" } return http.DetectContentType(buf[:n]) } func Download(url, path string) error { f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) stat, err := f.Stat() if err != nil { return err } defer f.Close() req, _ := http.NewRequest("GET", url, nil) req.Header.Set("Range", "bytes="+strconv.FormatInt(stat.Size(), 10)+"-") resp, err := http.DefaultClient.Do(req) if err != nil { return err } _, err = io.Copy(f, resp.Body) if err != nil { return err } return nil }