golang - 如何检查multipart.File信息

时间:2013-06-16 03:04:14

标签: file-upload go

当用户使用r.FormFile(“file”)上传文件时,会出现multipart.File,multipart.FileHeader和错误。

我的问题是如何获取有关上传文件的信息,例如,它的大小,如果它是图像,则是贬值,依此类推。

我根本不知道从哪里开始所以任何帮助都会很棒。

4 个答案:

答案 0 :(得分:8)

获取文件大小和MIME类型:

// Size constants
const (
        MB = 1 << 20
)

type Sizer interface {
        Size() int64
}

func Sample(w http.ResponseWriter, r *http.Request) error {
        if err := r.ParseMultipartForm(5 * MB); err != nil {
                return err
        }

        // Limit upload size
        r.Body = http.MaxBytesReader(w, r.Body, 5*MB) // 5 Mb

        //
        file, multipartFileHeader, err := r.FormFile("file")

        // Create a buffer to store the header of the file in
        fileHeader := make([]byte, 512)

        // Copy the headers into the FileHeader buffer
        if _, err := file.Read(fileHeader); err != nil {
                return err
        }

        // set position back to start.
        if _, err := file.Seek(0, 0); err != nil {
                return err
        }

        log.Printf("Name: %#v\n", multipartFileHeader.Filename)
        log.Printf("Size: %#v\n", file.(Sizer).Size())
        log.Printf("MIME: %#v\n", http.DetectContentType(fileHeader))
}

示例输出:

2016/12/01 15:00:06 Name: "logo_35x30_black.png"
2016/12/01 15:00:06 Size: 18674
2016/12/01 15:00:06 MIME: "image/png"

答案 1 :(得分:6)

可以从返回的multipart.FileHeader获取文件名和MIME类型。

大多数元数据将取决于文件类型。如果是图像,您应该能够使用标准库中的DecodeConfig函数,PNGJPEGGIF来获取尺寸(和颜色模型) )。

还有许多Go库可用于其他文件类型,它们具有类似的功能。

编辑:golang-nuts mail group上有一个很好的例子。

答案 2 :(得分:1)

您可以从Content-Length标题获取有关文件大小的大致信息。建议不要这样做,因为可以更改此标题。

更好的方法是使用ReadFrom方法:

clientFile, handler, err := r.FormFile("file") // r is *http.Request
var buff bytes.Buffer
fileSize, err := buff.ReadFrom(clientFile)
fmt.Println(fileSize) // this will return you a file size.

答案 3 :(得分:0)

我发现这种测试非常简单的另一种方法是将测试资产放置在相对于软件包的test_data目录中。通常,在测试文件中,我会创建一个辅助程序,该辅助程序将创建* http.Request实例,这使我可以轻松地在multipart.File上运行表测试(为简便起见,已删除错误)。

func createMockRequest(pathToFile string) *http.Request {
    file, err := os.Open(pathToFile)
    if err != nil {
        return nil
    }
    defer file.Close()

    body := &bytes.Buffer{}
    writer := multipart.NewWriter(body)
    part, err := writer.CreateFormFile("file", filepath.Base(pathToFile))
    if err != nil {
        return nil
    }
    _, _ = io.Copy(part, file)

    err = writer.Close()
    if err != nil {
        return nil
    }
    // the body is the only important data for creating a new request with the form data attached
    req, _ := http.NewRequest("POST", "", body)
    req.Header.Set("Content-Type", writer.FormDataContentType())
    return req
}