for (let i = 0; i < files.length; i++) {
formData.append('model_folder', files[i], files[i].webkitRelativePath);
}
前端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Upload Folder Example</title>
</head>
<body>
<input type="file" id="folderInput" webkitdirectory mozdirectory directory multiple>
<button onclick="uploadFolder()">Upload</button>
<script>
function uploadFolder() {
let input = document.getElementById('folderInput');
// 确保用户选择了一个文件夹
if (!input.files || !input.files.length) {
return alert('Please select a folder to upload.');
}
let files = input.files;
let formData = new FormData();
// 将文件的相对路径和文件对象添加到FormData中
for (let i = 0; i < files.length; i++) {
formData.append('model_folder', files[i], files[i].webkitRelativePath);
}
// 创建一个 XMLHttpRequest 对象进行异步请求
let request = new XMLHttpRequest();
request.open('POST', 'http://localhost:8089/digitalPerson/modeFile', true);
request.onload = function() {
if (request.status === 200) {
// 文件上传成功的处理
console.log(request.responseText);
} else {
// 文件上传失败的处理
console.error(request.responseText);
}
};
// 发送FormData对象到服务器
request.send(formData);
}
</script>
</body>
</html>
package controllers
import (
"PsycheEpic/src/utils"
"errors"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"os"
"path/filepath"
"strings"
)
// 处理文件夹上传
func UploadFolderHandler(c *gin.Context, digitalId int64) error {
err := c.Request.ParseMultipartForm(0) // 不限制上传文件大小
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": 0,
"message": err.Error(),
})
return errors.New("获取上传的文件失败")
}
//digitalId := 3
// 数字人ID转换为字符串
digital_Id := utils.Strval(digitalId)
modePath := filepath.Join("./static/HuaSoul/asset/", digital_Id)
fmt.Println("digitalId: ", digitalId)
// 检查上传的文件是否存在
form, err := c.MultipartForm()
files := form.File["model_folder"] // 'files' 是前端 JavaScript 中指定的字段名
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": 0,
"message": "missing uploaded file"})
return errors.New("丢失上传的文件")
}
// 创建模型文件夹
if err := os.MkdirAll(modePath, 0755); err != nil {
c.JSON(http.StatusOK, gin.H{
"code": 0,
"message": "failed to create model folder",
})
return errors.New("failed to create model folder")
}
// 遍历上传的文件
for _, file := range files {
fileName := file.Header["Content-Disposition"]
path, _ := GetFileName(fileName)
fmt.Println("path: ", path)
savePath := filepath.Join(modePath, path) // 保存文件的路径,确保'uploads'文件夹已存在或自动创建
if err := c.SaveUploadedFile(file, savePath); err != nil {
c.String(http.StatusOK, fmt.Sprintf("'%s' could not be saved: %v", file.Filename, err))
return err
}
}
// 上传成功后返回响应
//c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
return nil
}
//fileName [form-data; name="model_folder"; filename="test/头像.jpg"] ;取出文件名
func GetFileName(fileName []string) (string, error) {
for _, f := range fileName {
// 判断字符串是否包含了需要查找的文件名关键字
if strings.Contains(f, `filename=`) {
// 按照 filename=" 分割
parts := strings.Split(f, `filename="`)
if len(parts) < 2 {
// 没有找到分隔符,跳到下一个元素
continue
}
// 按照 " 分割以获取实际的文件路径
filePathParts := strings.SplitN(parts[1], `"`, 2)
// 如果成功找到路径就返回
if len(filePathParts) >= 2 {
return filePathParts[0], nil // 返回找到的路径
}
}
}
// 如果没有找到,返回错误
return "", fmt.Errorf("no path found")
}