This commit is contained in:
2025-12-09 16:33:44 +08:00
parent 345af5e2a3
commit 1d42f5ea50
49 changed files with 12015 additions and 1 deletions

160
file.go Executable file
View File

@@ -0,0 +1,160 @@
package main
import (
"io"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
)
// ListFiles function: Traverse all files in the specified directory and return a slice of the file path
func ListFiles(dir string) ([]string, error) {
var files []string
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
files = append(files, path)
}
return nil
})
return files, err
}
// Get Content function: Read the content of a specified file and return it
func GetFileContent(filePath string) ([]byte, error) {
file, err := os.Open(filePath)
if err != nil {
return nil, err
}
defer file.Close()
// Get File Size
fileInfo, err := file.Stat()
if err != nil {
return nil, err
}
fileSize := fileInfo.Size()
// Read File Content
fileContent := make([]byte, fileSize)
_, err = file.Read(fileContent)
if err != nil {
return nil, err
}
return fileContent, nil
}
// fileHandler function: Handle file requests
func fileHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Server", "MeowMusicEmbeddedServer")
filePath := r.URL.Path
// 提前URL解码
decodedPath, decodeErr := url.QueryUnescape(filePath)
if decodeErr == nil {
// 兼容历史数据:将+替换为空格(仅当解码成功时)
decodedPath = strings.ReplaceAll(decodedPath, "+", " ")
filePath = decodedPath // 后续统一使用解码后路径
}
// 处理 /url/ 远程请求(保持不变)
if strings.HasPrefix(filePath, "/url/") {
// Extract the URL after "/url/"
urlPath := filePath[len("/url/"):]
// Decode the URL path in case it's URL encoded
decodedURL, err := url.QueryUnescape(urlPath)
if err != nil {
NotFoundHandler(w, r)
return
}
// Determine the protocol based on the URL path
var protocol string
if strings.HasPrefix(decodedURL, "http/") {
protocol = "http://"
} else if strings.HasPrefix(decodedURL, "https/") {
protocol = "https://"
} else {
NotFoundHandler(w, r)
return
}
// Remove the protocol part from the decoded URL
decodedURL = strings.TrimPrefix(decodedURL, "http/")
decodedURL = strings.TrimPrefix(decodedURL, "https/")
// Correctly concatenate the protocol with the decoded URL
decodedURL = protocol + decodedURL
// Create a new HTTP request to the decoded URL, without copying headers
req, err := http.NewRequest("GET", decodedURL, nil)
if err != nil {
NotFoundHandler(w, r)
return
}
// Send the request and get the response
client := &http.Client{}
resp, err := client.Do(req)
if err != nil || resp.StatusCode != http.StatusOK {
NotFoundHandler(w, r)
return
}
defer resp.Body.Close()
// Read the response body into a byte slice
fileContent, err := io.ReadAll(resp.Body)
if err != nil {
NotFoundHandler(w, r)
return
}
setContentType(w, decodedURL)
// Write file content to response
w.Write(fileContent)
return
}
// 统一使用解码后路径
fullPath := filepath.Join("./files", filePath)
fileContent, err := GetFileContent(fullPath)
// 特殊处理空music.mp3
isEmptyMusic := (err == nil && len(fileContent) == 0 && strings.HasSuffix(filePath, "/music.mp3"))
if err != nil || isEmptyMusic {
// 没有/空的music.mp3文件直接返回404
NotFoundHandler(w, r)
return
}
// 避免重复Content-Type设置
setContentType(w, filePath)
w.Write(fileContent)
}
func setContentType(w http.ResponseWriter, path string) {
ext := strings.ToLower(filepath.Ext(path))
contentTypes := map[string]string{
".mp3": "audio/mpeg",
".wav": "audio/wav",
".flac": "audio/flac",
".aac": "audio/aac",
".ogg": "audio/ogg",
".m4a": "audio/mp4",
".amr": "audio/amr",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".png": "image/png",
".gif": "image/gif",
".bmp": "image/bmp",
".svg": "image/svg+xml",
".webp": "image/webp",
".txt": "text/plain",
".lrc": "text/plain",
".mrc": "text/plain",
".json": "application/json",
}
if ct, ok := contentTypes[ext]; ok {
w.Header().Set("Content-Type", ct)
} else {
w.Header().Set("Content-Type", "application/octet-stream")
}
}