{"record":{"id":"796f4df6e84d990a","repo":"flipped-aurora/gin-vue-admin","slug":"err","errorCode":null,"errorMessage":"读取文件失败, err:","messagePattern":"读取文件失败, err:","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/utils/upload/minio_oss.go","lineNumber":60,"sourceCode":"func (m *Minio) UploadFile(ctx context.Context, file *multipart.FileHeader) (filePathres, key string, uploadErr error) {\n\tclient, err := newMinioClient()\n\tif err != nil {\n\t\tlogger.WithCtx(ctx).Mod(\"upload\").Err(err).Error(\"minio client 初始化失败\")\n\t\treturn \"\", \"\", errors.New(\"minio client 初始化失败, err:\" + err.Error())\n\t}\n\n\tf, openError := file.Open()\n\t// mutipart.File to os.File\n\tif openError != nil {\n\t\tlogger.WithCtx(ctx).Mod(\"upload\").Err(openError).Error(\"function file.Open() Failed\")\n\t\treturn \"\", \"\", errors.New(\"function file.Open() Failed, err:\" + openError.Error())\n\t}\n\n\tfilecontent := bytes.Buffer{}\n\t_, err = io.Copy(&filecontent, f)\n\tif err != nil {\n\t\tlogger.WithCtx(ctx).Mod(\"upload\").Err(err).Error(\"读取文件失败\")\n\t\treturn \"\", \"\", errors.New(\"读取文件失败, err:\" + err.Error())\n\t}\n\tf.Close() // 创建文件 defer 关闭\n\n\t// 对文件名进行加密存储\n\text := filepath.Ext(file.Filename)\n\tfilename := utils.MD5V([]byte(strings.TrimSuffix(file.Filename, ext))) + ext\n\tif global.GVA_CONFIG.Minio.BasePath == \"\" {\n\t\tfilePathres = \"uploads\" + \"/\" + time.Now().Format(\"2006-01-02\") + \"/\" + filename\n\t} else {\n\t\tfilePathres = global.GVA_CONFIG.Minio.BasePath + \"/\" + time.Now().Format(\"2006-01-02\") + \"/\" + filename\n\t}\n\n\t// 根据文件扩展名检测 MIME 类型\n\tcontentType := mime.TypeByExtension(ext)\n\tif contentType == \"\" {\n\t\tcontentType = \"application/octet-stream\"\n\t}\n","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/utils/upload/minio_oss.go#L42-L78","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (nginx)\nproxy_read_timeout 30s;   # large upload over slow link cut off mid-read\n// after (nginx)\nproxy_read_timeout 600s;\nproxy_request_buffering off;","handlingStrategy":"retry","validationCode":"if fileHeader == nil || fileHeader.Size <= 0 {\n    return errors.New(\"empty upload\")\n}\n// optional headroom/limit check to reject hopeless uploads early\nif fileHeader.Size > maxUploadSize {\n    return fmt.Errorf(\"upload too large: %d > %d\", fileHeader.Size, maxUploadSize)\n}","typeGuard":null,"tryCatchPattern":"filePath, key, err := minioUploader.UploadFile(ctx, fileHeader)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"读取文件失败\") {\n        // stream broke mid-read; typically transient — client should retry\n        return status.NewRetryableError(err) // or map to 503 with Retry-After\n    }\n    return err\n}","preventionTips":["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."],"tags":["file-upload","io","network","minio","go"],"backgroundTag":"request-body-truncated","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}