flipped-aurora/gin-vue-admin · error
读取文件失败, err:
Error message
读取文件失败, err:
What it means
This error is returned by Minio.UploadFile when io.Copy(&filecontent, f) fails while reading the opened multipart file into a bytes.Buffer before uploading to MinIO. It indicates the upload stream broke mid-read — typically a client disconnect or truncated request body.
Source
Thrown at server/utils/upload/minio_oss.go:60
func (m *Minio) UploadFile(ctx context.Context, file *multipart.FileHeader) (filePathres, key string, uploadErr error) {
client, err := newMinioClient()
if err != nil {
logger.WithCtx(ctx).Mod("upload").Err(err).Error("minio client 初始化失败")
return "", "", errors.New("minio client 初始化失败, err:" + err.Error())
}
f, openError := file.Open()
// mutipart.File to os.File
if openError != nil {
logger.WithCtx(ctx).Mod("upload").Err(openError).Error("function file.Open() Failed")
return "", "", errors.New("function file.Open() Failed, err:" + openError.Error())
}
filecontent := bytes.Buffer{}
_, err = io.Copy(&filecontent, f)
if err != nil {
logger.WithCtx(ctx).Mod("upload").Err(err).Error("读取文件失败")
return "", "", errors.New("读取文件失败, err:" + err.Error())
}
f.Close() // 创建文件 defer 关闭
// 对文件名进行加密存储
ext := filepath.Ext(file.Filename)
filename := utils.MD5V([]byte(strings.TrimSuffix(file.Filename, ext))) + ext
if global.GVA_CONFIG.Minio.BasePath == "" {
filePathres = "uploads" + "/" + time.Now().Format("2006-01-02") + "/" + filename
} else {
filePathres = global.GVA_CONFIG.Minio.BasePath + "/" + time.Now().Format("2006-01-02") + "/" + filename
}
// 根据文件扩展名检测 MIME 类型
contentType := mime.TypeByExtension(ext)
if contentType == "" {
contentType = "application/octet-stream"
}
View on GitHub (pinned to 3136500ef3)
Solutions
- Read the appended error: 'unexpected EOF'/'context canceled' means the client or a proxy dropped the connection — retry from the client and increase proxy timeouts.
- Increase reverse-proxy request/read timeouts (nginx proxy_read_timeout, LB idle timeout) to exceed the worst-case upload duration.
- Check and raise any body-size limits so large files aren't truncated mid-stream.
- For unreliable networks, implement client-side chunked/resumable upload logic rather than a single monolithic multipart POST.
Example fix
// before (nginx) proxy_read_timeout 30s; # large upload over slow link cut off mid-read // after (nginx) proxy_read_timeout 600s; proxy_request_buffering off;
Defensive patterns
Strategy: retry
Validate before calling
if fileHeader == nil || fileHeader.Size <= 0 {
return errors.New("empty upload")
}
// optional headroom/limit check to reject hopeless uploads early
if fileHeader.Size > maxUploadSize {
return fmt.Errorf("upload too large: %d > %d", fileHeader.Size, maxUploadSize)
} Try / catch
filePath, key, err := minioUploader.UploadFile(ctx, fileHeader)
if err != nil {
if strings.HasPrefix(err.Error(), "读取文件失败") {
// stream broke mid-read; typically transient — client should retry
return status.NewRetryableError(err) // or map to 503 with Retry-After
}
return err
} Prevention
- Set proxy/LB read timeouts longer than the slowest expected upload.
- Enable proxy_request_buffering off (nginx) so streams aren't double-buffered.
- Implement resumable/chunked uploads for large or mobile-heavy traffic.
- Monitor client-abort rates in access logs (499/cancelled contexts) to size timeouts.
When it happens
Trigger: UploadFile in progress and the client aborts the upload (browser close, network drop), a proxy terminates the connection due to timeouts, or the request body is truncated by size-limit middleware mid-transfer.
Common situations: Users cancelling large uploads; mobile clients on flaky connections; nginx/ALB idle timeouts shorter than the upload duration; request body size limits (e.g. http.MaxBytesReader) hit partway through streaming.
Related errors
- function io.Copy() failed, err:
- 读取下载结果失败: %w
- 保存技能包失败: %w
- result.Msg
- 目标解析为内网/环回/链路本地地址, 已被 SSRF 防护拒绝(可在任务上开启"允许内网"豁免)
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/796f4df6e84d990a.
Report an issue: GitHub.