【问题标题】:Illegal base64 data at input byte for seemingly valid png对于看似有效的 png,输入字节处的非法 base64 数据
【发布时间】:2021-03-16 01:55:47
【问题描述】:

我正在尝试解码从 javascript canvas 的 toDataURL 函数生成的数据 URL。

以下 golang 应用程序失败,错误为 illegal base64 data at input byte 129)

package main

import (
    "encoding/base64"
    "fmt"
    "net/url"
    "strings"
)

func main() {
    pngData := "iVBORw0KGgoAAAANSUhEUgAAAF0AAAABCAYAAAC8PaJPAAAABHNCSVQICAgIfAhkiAAAALVJREFUGFdt0MsKQVEYhuG9CeU0VgamihBl6hqMXYoLchduQFuKicyFARPn0/J+9Q2tevrba639H1YcQhhHUTTBACloFZHFw3FJbODj7xdxjSqmqGCHms+3vv8m3nDwWSA+vVcipjFHHlcMcUTBtcuueSHqfgzlVJ7Nn/o99s5Qf3v0sUAHK///JbahmZQ3gy4S96OZc9A90fkdepM6tNTHDOqz6T3NofeTluuqV82oHOrphNEPw3UwfBVmbU4AAAAASUVORK5CYII="
    pngData, err := url.PathUnescape(pngData)

    if err != nil {
        fmt.Printf("Failed to unescape", err.Error())
        return
    }
    pngData = strings.Replace(pngData, "+", "", -1)
    _, err = base64.URLEncoding.WithPadding(base64.NoPadding).DecodeString(pngData)
    if err != nil {
        fmt.Printf("Failed to decode", err.Error())
    }
}

如果我将 pngData 中的值传递给 web-based base64 to png converter,则生成图像没有问题。 (一条白色值的水平线)

我已经尝试过 StdEncoding、RawURLEncoding 和它们的 Raw 对应物。我也尝试过使用或不使用填充,并且我尝试了相同的 pngData 字符串,带有一个额外的 = 并且没有尾随 =。

对于 Golang 拒绝解码这些数据的原因有什么想法吗?

我从画布中获得的一些图像解码得很好。但有些人,比如这个,没有。

【问题讨论】:

    标签: go base64 png


    【解决方案1】:

    Steven Penny's answer 显示了一种方法来做到这一点,但我不得不问:

    • 你为什么打电话给url.PathUnescape?数据不包含路径转义字符(不包含%-encoding)。调用是无害的,但没有必要。

    • 您为什么使用备用编码 (URLEncoding)?正如我们在base64 package documentation 中看到的,标准编码和备用编码之间的区别在于备用编码使用-_ 代替+/。但是如果我们看数据字符串,它包含加号和斜线,并且没有破折号或下划线,所以它显然是用标准编码编码的。

    • 你为什么打电话给base64.NoPadding?输入数据以=结尾,这是一个填充字符。

    • 你为什么打电话给base64.NoPadding 通过 base64.URLEncoding.WithPadding(base64.NoPadding)?文档告诉我们,这可以拼写为base64.RawURLEncoding

    • 为什么你明确要求去掉 + 字符(不是一个好主意)而不是 / 字符?

    如果我们删除所有这些(并拆分一个长输入行以用于发布目的)我们会得到这个(playground link):

    package main
    
    import (
        "encoding/base64"
        "fmt"
    )
    
    func main() {
        data := "iVBORw0KGgoAAAANSUhEUgAAAF0AAAABCAYAAAC8PaJPAAAABH" +
            "NCSVQICAgIfAhkiAAAALVJREFUGFdt0MsKQVEYhuG9CeU0Vgam" +
            "ihBl6hqMXYoLchduQFuKicyFARPn0/J+9Q2tevrba639H1YcQh" +
            "hHUTTBACloFZHFw3FJbODj7xdxjSqmqGCHms+3vv8m3nDwWSA+" +
            "vVcipjFHHlcMcUTBtcuueSHqfgzlVJ7Nn/o99s5Qf3v0sUAHK/" +
            "//JbahmZQ3gy4S96OZc9A90fkdepM6tNTHDOqz6T3NofeTluuq" +
            "V82oHOrphNEPw3UwfBVmbU4AAAAASUVORK5CYII="
        b, err := base64.StdEncoding.DecodeString(data)
        if err != nil {
            fmt.Printf("Failed to decode: %s\n", err)
        } else {
            fmt.Printf("bytes begin with: %q\n", b[0:4])
        }
    }
    

    【讨论】:

    • 老实说,您的大多数问题的答案都是“因为没有其他方法在起作用”。我应该编辑我的答案,只包含相关细节。
    • 现在我已经削减了它,我了解到我所有尝试的修复都只是掩盖了真正的问题。我通过 URL 将 base64 数据传递到我的请求中,而 go 的 http servermux 正在删除导致无效数据的三斜杠 (///)。在将数据提供给我的处理程序之前,我已更改为(双)URL 编码数据。
    【解决方案2】:

    这似乎工作正常:

    package main
    
    import (
       "encoding/base64"
       "image"
       "image/png"
       "os"
       "strings"
    )
    
    func main() {
       s := `iVBORw0KGgoAAAANSUhEUgAAAF0AAAABCAYAAAC8PaJPAAAABHNCSVQICAgIfAhkiAAAALVJ
    REFUGFdt0MsKQVEYhuG9CeU0VgamihBl6hqMXYoLchduQFuKicyFARPn0/J+9Q2tevrba639H1YcQhhHU
    TTBACloFZHFw3FJbODj7xdxjSqmqGCHms+3vv8m3nDwWSA+vVcipjFHHlcMcUTBtcuueSHqfgzlVJ7Nn/
    o99s5Qf3v0sUAHK///JbahmZQ3gy4S96OZc9A90fkdepM6tNTHDOqz6T3NofeTluuqV82oHOrphNEPw3U
    wfBVmbU4AAAAASUVORK5CYII=`
       d := base64.NewDecoder(base64.StdEncoding, strings.NewReader(s))
       p, e := png.Decode(d)
       if e != nil {
          panic(e)
       }
       c, e := os.Create("a.png")
       if e != nil {
          panic(e)
       }
       png.Encode(c, p.(*image.NRGBA))
    }
    

    【讨论】:

      猜你喜欢
      • 2021-08-08
      • 1970-01-01
      • 1970-01-01
      • 2016-12-20
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 2018-06-18
      • 1970-01-01
      相关资源
      最近更新 更多