我正在使用 Grails 1.3.7。我有一些使用内置 base64Encode 函数和 base64Decode 函数的代码。在我对一些二进制数据进行编码然后解码生成的字符串并将其写入新文件的简单测试用例中,一切都很好。在这种情况下,文件是相同的。
但后来我编写了一个 Web 服务,将 base64 编码数据作为 POST 调用中的参数。虽然base64数据的长度和我传入函数的字符串是一样的,但是base64数据的内容是被修改的。我花了 DAYS 调试它,最后编写了一个测试 Controller ,将 base64 中的数据传递给发布,并使用正确的 base64 编码数据获取本地文件的名称,如:
data=AAA-base-64-data...&testFilename=/name/of/file/with/base64data
在测试函数中,我将传入数据参数中的每个字节与测试文件中的相应字节进行了比较。我发现输入数据参数中的每个“+”字符都以某种方式替换为“”(空格,序号 ascii 32)。嗯?什么可以做到这一点?
为了确保我是正确的,我添加了一行内容:
data = data.replaceAll(' ', '+')
果然数据解码完全正确。我用任意长的二进制文件尝试过它,现在它每次都可以工作。但是我终生无法弄清楚在帖子中修改数据参数以将 ord(43) 字符转换为 ord(32) 是什么?我知道加号是 base64 规范中 2 个在某种程度上依赖于平台的字符之一,但考虑到我现在在同一台机器上进行编码和解码,我非常困惑是什么原因造成的。当然我有一个“修复”,因为我可以让它工作,但我对我不理解的“修复”感到紧张。
代码太大,无法在这里发布,但我得到了这样的 base64 编码:
def inputFile = new File(inputFilename)
def rawData = inputFile.getBytes()
def encoded = rawData.encodeBase64().toString()
然后我将该编码字符串写入新文件,以便稍后可以将其用于测试。如果我按原样加载该文件,我会得到相同的原始数据:
def encodedFile = new File(encodedFilename)
String encoded = encodedFile.getText()
byte[] rawData = encoded.decodeBase64()
所以这一切都很好。现在假设我采用“编码”变量并将其添加到 POST 函数的参数中,如下所示:
String queryString = "data=$encoded"
String url = "http://localhost:8080/some_web_service"
def results = urlPost(url, queryString)
def urlPost(String urlString, String queryString) {
def url = new URL(urlString)
def connection = url.openConnection()
connection.setRequestMethod("POST")
connection.doOutput = true
def writer = new OutputStreamWriter(connection.outputStream)
writer.write(queryString)
writer.flush()
writer.close()
connection.connect()
return (connection.responseCode == 200) ? connection.content.text : "error $connection.responseCode, $connection.responseMessage"
}
在网络服务方面,在 Controller 中我得到这样的参数:
String data = params?.data
println "incoming data parameter has length of ${data.size()}" //confirm right size
//unless I run the following line, the data does not decode to the same source
data = data.replaceAll(' ', '+')
//as long as I replace spaces with plus, this decodes correctly, why?
byte[] bytedata = data.decodeBase64()
很抱歉长篇大论,但我真的很想了解为什么我必须执行“用加号替换空格”才能正确解码。请求参数中使用加号是否有问题?
最佳答案
填充 params
的任何内容都期望请求是 URL 编码形式(具体来说,application/x-www-form-urlencoded
,其中“+”表示空格) ,但您没有对其进行 URL 编码。我不知道你的语言提供了什么功能,但在伪代码中,queryString
应该由
concat(uri_escape("data"), "=", uri_escape(base64_encode(rawBytes)))
简化为
concat("data=", uri_escape(base64_encode(rawBytes)))
“+
”字符将替换为“%2B
”。
关于html - 奇怪的 Base64 编码/解码问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5628738/