Go语言实现图片转Base64存储PostgreSQL时输出异常问题求助
异常原因
- 文件指针位置错误
将上传的文件内容写入tempFile后,文件读写指针停留在文件末尾,后续直接读取tempFile时只能读到空字节,Base64编码中空字节对应的字符为A,因此会出现大量重复A的无效编码。 - JPEG转码逻辑变量作用域错误
在image/jpeg的分支中,你声明了局部变量buf := new(bytes.Buffer),该变量仅在当前分支生效,外层用于生成Base64的全局buf完全没有被赋值为转码后的PNG内容,转码逻辑完全失效。 - 上传大小限制配置错误
注释标注最大支持10MB上传,但r.ParseMultipartForm(1 << 2)实际仅配置了4字节的缓冲区,根本无法正常接收图片文件。 - PostgreSQL长度限制疑问解答
PostgreSQL的text类型默认支持最大1GB的存储长度,71000字符不存在长度限制问题。但Base64编码会比原始二进制数据大33%,更推荐使用bytea类型直接存储图片二进制,或是将图片存储到本地磁盘/对象存储,数据库仅存储文件路径,性能更优。
修复方案
对应问题逐一修正,还可以优化掉不必要的临时文件读写逻辑,直接操作内存中的文件字节减少IO开销,修正后的代码如下:
import "io" func HandleUpload(w http.ResponseWriter, r *http.Request, formFileName string) (string, string, string, error) { // 最大10MB上传限制,修正参数为10 << 20 r.ParseMultipartForm(10 << 20) file, handler, err := r.FormFile(formFileName) if err != nil { return "", "", "", nil } defer file.Close() fmt.Printf("Uploaded File: %+v\n", handler.Filename) fmt.Printf("File Size: %+v\n", handler.Size) fmt.Printf("MIME Header: %+v\n", handler.Header) fileBytes, err := io.ReadAll(file) if err != nil { log.Println(err) return "", "", "", err } // 写入临时文件的逻辑保留,跳过无用的写后重读逻辑 tempFile, err := ioutil.TempFile(TmpDirectory, "upload-*.png") if err != nil { log.Println(err) return "", "", "", err } defer tempFile.Close() if _, err := tempFile.Write(fileBytes); err != nil { log.Println(err) return "", "", "", err } fmt.Fprintf(w, "Successfully Uploaded File\n") contentType := http.DetectContentType(fileBytes) var encodeBuf []byte switch contentType { case "image/png": fmt.Println("Image type is already PNG.") encodeBuf = fileBytes case "image/jpeg": fmt.Println("Image type is JPG, converting it to PNG.") img, err := jpeg.Decode(bytes.NewReader(fileBytes)) if err != nil { return "", "", "", errors.Wrap(err, "unable to decode jpeg") } buf := new(bytes.Buffer) if err := png.Encode(buf, img); err != nil { return "", "", "", errors.Wrap(err, "unable to encode png") } // 把转码后的内容赋值给全局编码用变量 encodeBuf = buf.Bytes() default: return "", "", "", errors.New("unsupported image type") } imgBase64Str := base64.StdEncoding.EncodeToString(encodeBuf) filePath := filepath.Join(TmpDirectory, tempFile.Name()) return handler.Filename, filePath, imgBase64Str, nil }
内容的提问来源于stack exchange,提问作者CodingAddict
相关产品推荐
相关产品推荐

