为了账号安全,请及时绑定邮箱和手机立即绑定

使用 mime/multipart 上传会损坏文件

使用 mime/multipart 上传会损坏文件

Go
人到中年有点甜 2023-08-07 14:39:36
我写了一个服务器,有上传图片的路由。这是一个接收一些参数的表单:title、description和visibility。picture该页面还使用Authentication标题。func UploadPictureRoute(prv *services.Provider) http.HandlerFunc {    return func(w http.ResponseWriter, r *http.Request) {        user, err := auth.ValidateRequest(prv, w, r)        if auth.RespondError(w, err) {            return        }        r.ParseMultipartForm(10 << 20) // 10 meg max        title := r.FormValue("title")        desc := r.FormValue("description")        visib := r.FormValue("visibility")        visibInt, err := strconv.Atoi(visib)        visibility := int8(visibInt) // Visibility can be either 0, 1, 2        if err != nil {            w.WriteHeader(http.StatusBadRequest)        }        file, _, err := r.FormFile("picture")        if err != nil {            w.WriteHeader(http.StatusBadRequest)            return        }        defer file.Close()        mimeType, _, err := mimetype.DetectReader(file) // Package gabriel-vasile/mimetype        if err != nil {            w.WriteHeader(http.StatusBadRequest)            return        }        if !utils.IsValidMimetype(mimeType) { // Basically just comparing to image/png, image/jpg. Crashes here            w.WriteHeader(http.StatusBadRequest)            return        }        parentFolder := prv.PicturePath + "/" + strconv.FormatInt(*user.ID, 10) + "/"        _, err = os.Stat(parentFolder)        if os.IsNotExist(err) {            err = os.MkdirAll(parentFolder, os.ModePerm)            if err != nil {                w.WriteHeader(http.StatusInternalServerError)                return            }        }        pict := model.Picture{            Title:       title,            Description: desc,            Creator:     &user,            Visibility:  visibility,            Ext:         utils.GetExtForMimetype(mimeType),        }这段代码会导致服务器崩溃。图片的mimetype变成application/octet-stream并且图像标题被破坏(它仍然在某些编辑器中打开,但EyesOfGnome基本上说图片不是JPG/PNG文件,因为它找不到开头的幻数)如何修复HTTP go客户端才能成功上传图片?
查看完整描述

1 回答

?
慕少森

TA贡献2019条经验 获得超9个赞

调用mimetype.DetectReader(file)读取部分文件。调用 _, err = io.Copy(pict, file)读取文件的其余部分。要读取整个文件,请回溯到调用 之前的偏移量 0 io.Copy。


文件在偏移量 0 处打开。调用 后无需立即查找偏移量 0 Open。


通过交换调用顺序来修复问题:


...


mime, _, err := mimetype.DetectReader(file)

if err != nil {

    fmt.Println("Can't read the file")

    return

}


// Rewind to the start of the file

_, err = file.Seek(0, io.SeekStart)

if err != nil {

    fmt.Println("Can't read the file")

    return

}


...

服务器也有类似的问题。检测类型后回退:


mimeType, _, err := mimetype.DetectReader(file) // Package gabriel-vasile/mimetype

if err != nil {

    w.WriteHeader(http.StatusBadRequest)

    return

}


// Rewind to the start of the file

_, err = file.Seek(0, io.SeekStart)

if err != nil {

    w.WriteHeader(http.StatusInternalServerError)

    return

}


查看完整回答
反对 回复 2023-08-07
  • 1 回答
  • 0 关注
  • 84 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信