在 GoLang 中将图像转换为 Base64

Converting Images to Base64 in GoLang

我正在尝试使用 Base64 编码转换图像并将它们保存到数据库中。这是我的程序:

  1. HTML 页面显示一个用于浏览图像的按钮
  2. 正在通过以下代码处理图像:
func HandleUpload(w http.ResponseWriter, r *http.Request, formFileName string) (string, string, string, error) {
    // Maximum upload of 10 MB files
    r.ParseMultipartForm(1 << 2)

    file, handler, err := r.FormFile(formFileName)
    if err != nil {
        // If there is an error that means form is empty. Return nil for err in order
        // to validate result as required.
        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)

    tempFile, err := ioutil.TempFile(TmpDirectory, "upload-*.png")
    if err != nil {
        log.Println(err)
        return "", "", "", err
    }

    defer tempFile.Close()

    fileBytes, err := ioutil.ReadAll(file)
    if err != nil {
        log.Println(err)
        return "", "", "", err
    }

    tempFile.Write(fileBytes)
    fmt.Fprintf(w, "Successfully Uploaded File\n")

    // create a new buffer base on file size
    fInfo, _ := tempFile.Stat()
    var size int64 = fInfo.Size()
    buf := make([]byte, size)

    // read file content into buffer
    fReader := bufio.NewReader(tempFile)
    fReader.Read(buf)

    contentType := http.DetectContentType(fileBytes)

    switch contentType {
    case "image/png":
        fmt.Println("Image type is already PNG.")
    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")
        }
    }
    //convert the buffer bytes to base64 string - use buf.Bytes() for new image
    imgBase64Str := base64.StdEncoding.EncodeToString(buf)

    filePath := filepath.Join(TmpDirectory, tempFile.Name())
    return handler.Filename, filePath, imgBase64Str, nil}
  1. 返回的 ImageBase64Str 被写入数据库,尽管我认为 PostgreSQL 数据库在输入时可以接受一个限制。我的 ImageBase64Str71000 个字符! 为什么?它看起来像这样:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...

我假设这不是预期的输出。

有人可以帮忙吗?

语句buf := make([]byte, size)分配了一片零字节。语句 imgBase64Str := base64.StdEncoding.EncodeToString(buf) 将那些零字节编码为 base64,给出 result you observe.

数据的 base64 编码比原始数据大 4 / 3 倍。大图像将产生大编码。

函数不需要临时文件。使用从表单文件中提取的字节。

这是代码的简化和修复版本:

func HandleUpload(w http.ResponseWriter, r *http.Request, formFileName string) (string, string, error) {
    // Maximum upload of 10 MB files r.ParseMultipartForm(1 << 2)

    file, hdr, err := r.FormFile(formFileName)
    if err != nil {
        // If there is an error that means form is empty. Return nil for err in order
        // to validate result as required.
        return "", "", nil
    }

    defer file.Close()
    data, err := ioutil.ReadAll(file)
    if err != nil {
        log.Println(err)
        return "", "", err
    }

    contentType := http.DetectContentType(data)

    switch contentType {
    case "image/png":
        fmt.Println("Image type is already PNG.")
    case "image/jpeg":
        img, err := jpeg.Decode(bytes.NewReader(data))
        if err != nil {
            return "", "", fmt.Errorf("unable to decode jpeg: %w", err)
        }

        var buf bytes.Buffer
        if err := png.Encode(&buf, img); err != nil {
            return "", "", fmt.Errorf("unable to encode png: %w", err)
        }
        data = buf.Bytes()
    default:
        return "", "", fmt.Errorf("unsupported content typo: %s", contentType)
    }
    imgBase64Str := base64.StdEncoding.EncodeToString(data)
    return hdr.Filename, imgBase64Str, nil
}