[web] Golang中不创建文件的实现方法与问题探讨

[web] Golang中不创建文件的实现方法与问题探讨 我有这段代码,任务是上传文件。当我点击上传按钮时,文件没有在tmp目录中创建,我手动创建了目录,仅在本地机器上进行了测试。有什么想法吗?

package main

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

const (
CONN_HOST = "localhost"
CONN_PORT = "8089"
)

func fileHandler(w http.ResponseWriter, r *http.Request) {
file, header, err := r.FormFile("file")
if err != nil {
	log.Printf("error getting a file for the provided form key : ", err)
	return
}

defer file.Close()

out, pathError := os.Create("/tmp/uploadedFile")
if pathError != nil {
	log.Printf("error creating a file for writing : ", pathError)
	return
}
defer out.Close()

_, copyFileError := io.Copy(out, file)

if copyFileError != nil {
	log.Printf("error occurred while file copy : ", copyFileError)
}

fmt.Fprintf(w, "File uploaded successfully : "+header.Filename)
}

func index(w http.ResponseWriter, r *http.Request) {
parsedTemplate, _ := template.ParseFiles("templates/upload-file.html")
parsedTemplate.Execute(w, nil)
}

func main() {
http.HandleFunc("/", index)
http.HandleFunc("/upload", fileHandler)
err := http.ListenAndServe(CONN_HOST+":"+CONN_PORT, nil)
if err != nil {
	log.Fatal("error starting http server : ", err)
	return
}
}

更多关于[web] Golang中不创建文件的实现方法与问题探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

现在可以正常工作了,谢谢!

更多关于[web] Golang中不创建文件的实现方法与问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


您的代码可以完美地将文件上传到 /tmp 目录中

您可以通过以下修改来检查代码

out, pathError := os.Create("/tmp/uploadedFile")

改为

currDir, _ := os.Getwd() // 获取当前目录路径
out, pathError := os.Create(currDir + "/" + header.Filename)

在你的代码中,文件上传功能没有在/tmp目录创建文件,可能有几个原因。以下是具体分析和修改建议:

问题分析

  1. 硬编码的文件路径os.Create("/tmp/uploadedFile") 总是创建同名文件,会覆盖之前的文件
  2. 缺少表单解析:需要在获取文件前调用 r.ParseMultipartForm()
  3. 权限问题:可能没有在/tmp目录的写入权限
  4. 文件命名:应该使用上传文件的原始名称

修正后的代码

package main

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

const (
    CONN_HOST = "localhost"
    CONN_PORT = "8089"
    UPLOAD_DIR = "./uploads" // 使用相对路径,避免权限问题
)

func fileHandler(w http.ResponseWriter, r *http.Request) {
    // 解析表单,限制上传大小为10MB
    err := r.ParseMultipartForm(10 << 20)
    if err != nil {
        log.Printf("Error parsing multipart form: %v", err)
        http.Error(w, "Error parsing form", http.StatusBadRequest)
        return
    }

    // 获取上传的文件
    file, header, err := r.FormFile("file")
    if err != nil {
        log.Printf("Error getting file from form: %v", err)
        http.Error(w, "Error retrieving file", http.StatusBadRequest)
        return
    }
    defer file.Close()

    // 创建上传目录(如果不存在)
    if err := os.MkdirAll(UPLOAD_DIR, 0755); err != nil {
        log.Printf("Error creating upload directory: %v", err)
        http.Error(w, "Error creating directory", http.StatusInternalServerError)
        return
    }

    // 使用原始文件名创建文件
    filePath := filepath.Join(UPLOAD_DIR, header.Filename)
    out, err := os.Create(filePath)
    if err != nil {
        log.Printf("Error creating file: %v", err)
        http.Error(w, "Error creating file", http.StatusInternalServerError)
        return
    }
    defer out.Close()

    // 复制文件内容
    _, err = io.Copy(out, file)
    if err != nil {
        log.Printf("Error copying file: %v", err)
        http.Error(w, "Error saving file", http.StatusInternalServerError)
        return
    }

    fmt.Fprintf(w, "File uploaded successfully: %s", header.Filename)
    log.Printf("File saved to: %s", filePath)
}

func index(w http.ResponseWriter, r *http.Request) {
    parsedTemplate, err := template.ParseFiles("templates/upload-file.html")
    if err != nil {
        http.Error(w, "Error loading template", http.StatusInternalServerError)
        return
    }
    parsedTemplate.Execute(w, nil)
}

func main() {
    http.HandleFunc("/", index)
    http.HandleFunc("/upload", fileHandler)
    
    log.Printf("Server starting on %s:%s", CONN_HOST, CONN_PORT)
    err := http.ListenAndServe(CONN_HOST+":"+CONN_PORT, nil)
    if err != nil {
        log.Fatal("Error starting http server: ", err)
    }
}

关键修改点

  1. 添加表单解析r.ParseMultipartForm(10 << 20) 解析表单并限制上传大小
  2. 使用相对路径:改为 ./uploads 目录,避免系统目录权限问题
  3. 动态创建目录os.MkdirAll() 确保上传目录存在
  4. 保留原始文件名:使用 header.Filename 作为保存的文件名
  5. 改进错误处理:添加了适当的HTTP错误响应

对应的HTML模板示例

确保你的 templates/upload-file.html 包含正确的表单:

<!DOCTYPE html>
<html>
<head>
    <title>File Upload</title>
</head>
<body>
    <h2>Upload File</h2>
    <form action="/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="file" required>
        <input type="submit" value="Upload">
    </form>
</body>
</html>

这些修改应该能解决文件创建的问题。主要问题很可能是缺少 r.ParseMultipartForm() 调用和系统目录的权限限制。

回到顶部