go限制文件名上传

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
)

const (
	uploadDir     = "./uploads"           // 文件存储目录
	maxUploadSize = 10 << 20              // 10MB 最大文件大小
	fileNameRegex = `^[a-zA-Z0-9_\-\.]+$` // 文件名正则规则
)

var validFileName = regexp.MustCompile(fileNameRegex)

func main() {
	// 创建上传目录
	if err := os.MkdirAll(uploadDir, 0755); err != nil {
		panic(err)
	}

	http.HandleFunc("/upload", uploadHandler)
	http.Handle("/files/", http.StripPrefix("/files/",
		http.FileServer(http.Dir(uploadDir))))

	fmt.Println("Server started at :9090")
	http.ListenAndServe(":9090", nil)
}

// 上传处理函数
func uploadHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	// 解析上传文件
	r.Body = http.MaxBytesReader(w, r.Body, maxUploadSize)
	file, header, err := r.FormFile("file")
	if err != nil {
		http.Error(w, "Invalid file", http.StatusBadRequest)
		return
	}
	defer file.Close()

	// 校验文件名格式
	if !validFileName.MatchString(header.Filename) {
		http.Error(w, "Invalid file name format", http.StatusBadRequest)
		return
	}

	// 创建目标文件
	targetPath := filepath.Join(uploadDir, header.Filename)
	dst, err := os.Create(targetPath)
	if err != nil {
		http.Error(w, "Failed to create file", http.StatusInternalServerError)
		return
	}
	defer dst.Close()

	// 复制文件内容
	if _, err := io.Copy(dst, file); err != nil {
		http.Error(w, "Failed to save file", http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusCreated)
	fmt.Fprintf(w, "File %s uploaded successfully", header.Filename)
}
posted @ 2025-04-06 09:34  卓能文  阅读(10)  评论(0)    收藏  举报