10

当用户上传文件时,使用 r.FormFile("file") 你会得到一个 multipart.File、一个 multipart.FileHeader 和一个错误。

我的问题是如何获取有关上传文件的信息,例如,它的大小,如果是图像,它的尺寸等等。

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

4

4 回答 4

16

要获取文件大小和 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"
于 2016-12-01T23:03:04.787 回答
9

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

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

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

编辑:golang-nuts邮件组上有一个很好的例子。

于 2013-06-16T10:13:01.143 回答
1

我发现这种类型的测试非常简单的另一种方法是将测试资产放在相对于包的 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
}
于 2019-09-18T02:05:46.017 回答
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.
于 2016-07-04T02:21:13.537 回答