英文:
golang - How to check multipart.File information
问题
当用户使用r.FormFile("file")
上传文件时,您会得到一个multipart.File
,一个multipart.FileHeader
和一个error
。
我的问题是如何仅获取有关上传文件的信息。例如,它的大小,如果是图像的话,它的尺寸等等。
我真的不知道从哪里开始,所以任何帮助都将是很好的。
英文:
When a user uploads a file using r.FormFile("file")
you get a multipart.File
, a multipart.FileHeader
and an error
.
My question is how to just obtain information about the uploaded file . For example, its size, its dimensions if it's an image, and so on and so forth.
I have literally got no idea on where to start so any help would be great.
答案1
得分: 20
// 获取文件大小和MIME类型:
// 大小常量
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
}
// 限制上传大小
r.Body = http.MaxBytesReader(w, r.Body, 5*MB) // 5 Mb
//
file, multipartFileHeader, err := r.FormFile("file")
// 创建一个缓冲区来存储文件的头部
fileHeader := make([]byte, 512)
// 将头部复制到FileHeader缓冲区中
if _, err := file.Read(fileHeader); err != nil {
return err
}
// 将位置设置回起始位置
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"
英文:
To get the file size and MIME type:
// 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))
}
Sample output:
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"
答案2
得分: 8
文件名和MIME类型可以从返回的multipart.FileHeader
中获取。
大多数其他元数据将取决于文件类型。如果是图像文件,您应该能够使用标准库中的DecodeConfig
函数,例如PNG
,JPEG
和GIF
,以获取尺寸(和颜色模型)。
还有许多其他文件类型的Go库可用,它们将具有类似的功能。
编辑:golang-nuts
邮件组上有一个很好的示例。
英文:
The file name and MIME type can be obtained from the returned multipart.FileHeader
.
Most further meta-data will depend on the file type. If it's an image, you should be able to use the DecodeConfig
functions in the standard library, for PNG
, JPEG
and GIF
, to obtain the dimensions (and color model).
There are many Go libraries available for other file types as well, which will have similar functions.
EDIT: There's a good example on the golang-nuts
mail group.
答案3
得分: 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
}
// body是创建带有附加表单数据的新请求的唯一重要数据
req, _ := http.NewRequest("POST", "", body)
req.Header.Set("Content-Type", writer.FormDataContentType())
return req
}
英文:
Another way I've found pretty simple for this type of testing is to place test assets in a test_data directory relative to the package. Within my test file I normally create a helper that creates an instance of *http.Request, which allows me to run table test pretty easily on multipart.File, (errors checking removed for brevity).
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
}
答案4
得分: 0
你可以从Content-Length
头部获取文件的大致大小信息。这种方法不推荐使用,因为该头部可能会被更改。
更好的方法是使用ReadFrom方法:
clientFile, handler, err := r.FormFile("file") // r是*http.Request
var buff bytes.Buffer
fileSize, err := buff.ReadFrom(clientFile)
fmt.Println(fileSize) // 这将返回文件的大小。
英文:
You can get approximate information about the size of file from Content-Length
header. This is not recommended, because this header can be changed.
A better way is to use ReadFrom method:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论