GIN-debug\] Listening and serving HTTP on 0.0.0.0:8080 2026/02/03 22:18:05 🛡️ AuthMiddleware: Set user_id in context: 1 2026/02/03 22:18:05 🚀 uploadCover function started! 2026/02/03 22:18:05 📁 \[START\] saveUploadedFileV2 called 2026/02/03 22:18:05 📁 Input params - prefix: 'product_cover', userID: 1 2026/02/03 22:18:05 📁 Received file - Filename: 'b4f8410b-de1d-4977-beef-e695a36ed341.tmp', Size: 704872 bytes 2026/02/03 22:18:05 📁 Extracted file extension: '.tmp' 2026/02/03 22:18:05 ❌ Unsupported file type! 2026/02/03 22:18:05 📁 Allowed extensions: \[.jpeg .png .gif .mov .avi .mkv .mp3 .wav .jpg .mp4 .m4a
GIN\] 2026/02/03 - 22:18:05 \| 500 \| 72.4501ms \| 192.168.0.104 \| POST "/api/product/upload-cover" 2026/02/03 22:19:56 C:/Users/Administrator/Desktop/and-app/main.go:5692 \[14.049ms\] \[rows:0\] SELECT 1 \[GIN\] 2026/02/03 - 22:19:56 \| 200 \| 159.2627ms \| 192.168.0.100 \| GET "/health"
🎯 问题根源
你的 Android 客户端上传的文件名是 b4f8410b-de1d-4977-beef-e695a36ed341.tmp。
服务端从这个文件名中提取出的扩展名是 .tmp。
你的服务端代码只允许特定的扩展名(如 .jpg, .png, .mp4 等),.tmp 不在允许列表中。
因此,saveUploadedFileV2 函数返回了一个错误:"unsupported file type: .tmp"。
❓ 为什么返回的是 500 而不是 400?
这是一个关键点。函数正确地返回了 error,但最终 HTTP 状态码却是 500。
这几乎可以肯定是因为你的 uploadCover 处理函数没有正确处理这个 error 并返回一个 HTTP 响应。
当 Gin 的 handler 函数执行完毕后,如果没有调用 c.JSON, c.String, c.HTML 等方法向客户端写入任何数据,Gin 框架会认为这是一个"无响应"的请求。它的内置 Recovery 中间件会捕获到这种情况,并记录为一个 500 Internal Server Error。
🛠️ 解决方案
你需要做两件事:
第一步:修复 Android 客户端(推荐)
在 Android 端,当你从 Uri 创建临时文件时,不要使用 .tmp 作为后缀,而是根据文件的真实 MIME 类型来设置正确的扩展名。
你已经在日志中打印了 MIME 类型:
log
编辑
I DEBUG uploadFunc... (MIME: image/jpeg)
你可以利用这个信息。修改你的 uploadFunc 或相关文件创建逻辑,大致如下:
Kotlin 示例 (概念性代码):
kotlin
编辑
// 假设你已经获取到了 mimeType, 例如 "image/jpeg"
val fileExtension = when (mimeType) {
"image/jpeg" -> ".jpg"
"image/png" -> ".png"
"video/mp4" -> ".mp4"
// ... 其他类型
else -> ".bin" // 默认情况
}
val tempFile = File.createTempFile("upload_", fileExtension, cacheDir)
// ... 将内容写入 tempFile
这样,上传到服务端的文件名就会是 xxx.jpg,而不是 xxx.tmp,问题就彻底解决了。
第二步:修复 Go 服务端的错误处理(必须做)
即使你修复了客户端,服务端也应该有健壮的错误处理。请立即修改 uploadCover 函数,确保它在任何情况下都会返回一个 HTTP 响应。
go
编辑
func uploadCover(c *gin.Context, contentType ContentType) {
log.Println("🚀 uploadCover function started!")
// 调用上传逻辑
url, err := UploadFile(c, PREFIX_PRODUCT_CAROUSEL, "cover")
if err != nil {
// 👇 关键:必须在这里返回一个 JSON 响应!
log.Printf("❌ uploadCover failed: %v", err)
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 成功时也返回响应
c.JSON(http.StatusOK, gin.H{"url": url})
}
做了这个修改后,如果再发生类似错误,客户端收到的将不再是神秘的 500,而是一个清晰的 400 Bad Request 和具体的错误信息 "unsupported file type: .tmp",这会让调试变得非常容易。
✅ 总结
表格
问题 原因 解决方案
服务器返回 500 错误 1. 客户端上传了 .tmp 文件。
. 服务端拒绝了该类型并返回 error。
. uploadCover 函数未处理此 error,导致无 HTTP 响应。 1. (服务端) 修改 uploadCover,确保所有分支都调用 c.JSON。
. (客户端) 在创建临时文件时,使用正确的文件扩展名(如 .jpg)。
请优先完成第二步(修复服务端错误处理),这能立刻让你看到真实的错误原因。然后再去优化客户端,从根本上解决问题。