使用Go上传PNG图片到MinIO时报no such file or directory错误如何解决
错误原因
触发报错的核心原因是FPutObject参数逻辑传递错误,同时没有正确处理Gin框架上传的临时文件:
minio.FPutObject的第四个参数要求填写本地待上传文件的路径,你传递的是期望存到MinIO侧的路径/sensors/xxx.png,本地服务器不存在该路径,直接触发找不到文件的错误。- 你当前通过
c.FormFile仅拿到了上传文件的元数据,没有将用户上传的文件存储到本地磁盘,就算填对本地路径也会找不到对应文件。 - 额外参数错误:你当前
FPutObject第三个参数(MinIO侧存储的对象名)仅填了原始文件名,没有带sensors/前缀,就算上传成功文件也不会存入你提前创建的sensors目录下。 - 隐藏bug:原有代码上传成功后使用了
utilities.Info.Panicf打印结果,会直接触发panic终止程序,需要修改为普通日志打印方法。
修复方案
推荐直接使用PutObject方法读取文件流上传,无需额外将文件存到本地磁盘,修改fileNormalIcon != nil分支内的逻辑即可:
if fileNormalIcon != nil { // 打开上传的文件流 src, err := fileNormalIcon.Open() if err != nil { utilities.Error.Printf("Open upload file error: %s", err) response[config.MESSAGE_RESPONSE_INDEX] = fmt.Sprintf("err: %s", err.Error()) c.JSON(http.StatusInternalServerError, response) return } defer src.Close() // 拼接MinIO侧的存储路径,存入sensors目录 objectName := "sensors/" + fileNormalIcon.Filename // 调用PutObject上传流,无需本地存储文件 output, err := minioClient.PutObject(ctx, bucketName, objectName, src, fileNormalIcon.Size, minio.PutObjectOptions{ContentType: contentType}) if err != nil { utilities.Error.Printf("Error upload image to bucket: %s", err) response[config.MESSAGE_RESPONSE_INDEX] = fmt.Sprintf("err: %s", err.Error()) c.JSON(http.StatusInternalServerError, response) return } utilities.Info.Printf("upload result: %+v", output) data["normal_icon"] = objectName dataUpdateExist = true }
可选方案(坚持使用FPutObject的场景)
如果需要先将文件存到本地再上传,可以先将Gin上传的文件保存到本地临时目录,再调用FPutObject:
import "os" // ... 其他原有代码不变 if fileNormalIcon != nil { // 先创建本地临时存储目录(如果不存在) if err := os.MkdirAll("./temp", 0755); err != nil { utilities.Error.Printf("Create temp dir error: %s", err) response[config.MESSAGE_RESPONSE_INDEX] = fmt.Sprintf("err: %s", err.Error()) c.JSON(http.StatusInternalServerError, response) return } // 自定义本地临时存储路径 localTempPath := "./temp/" + fileNormalIcon.Filename // 保存上传的文件到本地 if err := c.SaveUploadedFile(fileNormalIcon, localTempPath); err != nil { utilities.Error.Printf("Save upload file to local error: %s", err) response[config.MESSAGE_RESPONSE_INDEX] = fmt.Sprintf("err: %s", err.Error()) c.JSON(http.StatusInternalServerError, response) return } // 拼接MinIO侧的存储路径 objectName := "sensors/" + fileNormalIcon.Filename // 调用FPutObject上传本地文件 output, err := minioClient.FPutObject(ctx, bucketName, objectName, localTempPath, minio.PutObjectOptions{ContentType: contentType}) if err != nil { utilities.Error.Printf("Error upload image to bucket: %s", err) response[config.MESSAGE_RESPONSE_INDEX] = fmt.Sprintf("err: %s", err.Error()) c.JSON(http.StatusInternalServerError, response) return } // 上传完成后可以选择删除本地临时文件释放磁盘 _ = os.Remove(localTempPath) utilities.Info.Printf("upload result: %+v", output) data["normal_icon"] = objectName dataUpdateExist = true }
内容的提问来源于stack exchange,提问作者Titanio Yudista
相关产品推荐
相关产品推荐

