如何使用Golang从HTML上传目录到服务器

如何使用Golang从HTML上传目录到服务器 我正在做一个学校项目。需要从HTML输入中将文件夹上传到我的后端Go服务器。我找不到任何关于上传文件夹的教程,而我找到的所有教程都在讨论上传文件。

希望有人能帮我解决这个问题!!非常感谢!

2 回复

你可以在文件传输前简单地创建那些文件夹。

更多关于如何使用Golang从HTML上传目录到服务器的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go语言中,通过HTML表单上传文件夹需要利用浏览器的文件选择器支持目录上传功能(通过<input type="file" webkitdirectory>),并在后端处理多文件上传。以下是一个完整的示例,包括HTML前端和Go后端代码。

1. HTML前端代码

创建一个HTML表单,允许用户选择并上传整个文件夹:

<!DOCTYPE html>
<html>
<head>
    <title>上传文件夹</title>
</head>
<body>
    <form action="/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="files" webkitdirectory directory multiple>
        <input type="submit" value="上传文件夹">
    </form>
</body>
</html>

注意:webkitdirectorydirectory属性使文件选择器支持文件夹上传,multiple允许选择多个文件(即文件夹中的所有文件)。

2. Go后端代码

使用标准库net/httphtml/template处理上传请求。以下Go代码设置了一个简单的HTTP服务器,包括上传处理程序:

package main

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

const uploadPath = "./uploads" // 定义上传文件存储目录

func main() {
	// 确保上传目录存在
	os.MkdirAll(uploadPath, os.ModePerm)

	// 设置路由
	http.HandleFunc("/", indexHandler)
	http.HandleFunc("/upload", uploadHandler)

	fmt.Println("服务器启动在 :8080")
	http.ListenAndServe(":8080", nil)
}

// 首页处理器,显示上传表单
func indexHandler(w http.ResponseWriter, r *http.Request) {
	tmpl := template.Must(template.New("index").Parse(`
<!DOCTYPE html>
<html>
<head>
    <title>上传文件夹</title>
</head>
<body>
    <form action="/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="files" webkitdirectory directory multiple>
        <input type="submit" value="上传文件夹">
    </form>
</body>
</html>
`))
	tmpl.Execute(w, nil)
}

// 上传处理器
func uploadHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "只支持POST请求", http.StatusMethodNotAllowed)
		return
	}

	// 解析多部分表单,限制上传大小为32MB
	err := r.ParseMultipartForm(32 << 20)
	if err != nil {
		http.Error(w, "无法解析表单: "+err.Error(), http.StatusBadRequest)
		return
	}

	// 获取文件列表
	files := r.MultipartForm.File["files"]
	if len(files) == 0 {
		http.Error(w, "未选择文件", http.StatusBadRequest)
		return
	}

	// 遍历并保存每个文件
	for _, fileHeader := range files {
		file, err := fileHeader.Open()
		if err != nil {
			http.Error(w, "无法打开文件: "+err.Error(), http.StatusInternalServerError)
			return
		}
		defer file.Close()

		// 创建目标文件路径
		targetPath := filepath.Join(uploadPath, fileHeader.Filename)
		targetFile, err := os.Create(targetPath)
		if err != nil {
			http.Error(w, "无法创建文件: "+err.Error(), http.StatusInternalServerError)
			return
		}
		defer targetFile.Close()

		// 复制文件内容
		_, err = io.Copy(targetFile, file)
		if err != nil {
			http.Error(w, "写入文件失败: "+err.Error(), http.StatusInternalServerError)
			return
		}
	}

	fmt.Fprintf(w, "成功上传 %d 个文件", len(files))
}

关键点说明:

  1. 前端限制webkitdirectory属性主要在基于WebKit的浏览器(如Chrome、Edge)中工作。其他浏览器可能不支持文件夹上传。
  2. 文件路径:上传的文件会保留原始文件名,但不会保留完整的目录结构。如果需要保留目录结构,需要在表单中包含相对路径信息(这通常需要额外的JavaScript处理)。
  3. 错误处理:示例中包含基础错误处理,生产环境需要更完善的错误管理和安全措施(如文件类型检查、大小限制)。
  4. 并发安全:在高并发场景下,需考虑文件命名冲突和目录操作锁。

运行此代码后,访问http://localhost:8080即可测试文件夹上传功能。所有上传的文件将保存在项目目录下的uploads文件夹中。

回到顶部