奇怪的Base64 EN code /德code问题 [英] Strange Base64 encode/decode problem

查看:258
本文介绍了奇怪的Base64 EN code /德code问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Grails 1.3.7。我有一个使用内置base64En code函数和base64De code函数一些code。这一切工作正常,在简单的测试情况下,我带code一些二进制数据,然后去code生成的字符串,并将其写入到一个新文件。在这种情况下的文件是相同的。

I'm using Grails 1.3.7. I have some code that uses the built-in base64Encode function and base64Decode function. It all works fine in simple test cases where I encode some binary data and then decode the resulting string and write it to a new file. In this case the files are identical.

但后来我写了以base64 EN codeD数据作为一个POST调用的参数的Web服务。虽然BASE64数据的长度是相同的我传递到函数字符串,以base64数据的内容被修改。我花几天调试这最后写道,传递的数据为Base64后,也采取了本地文件的名称与正确的base64 EN codeD数据,如在测试控制器:

But then I wrote a web service that took the base64 encoded data as a parameter in a POST call. Although the length of the base64 data is identical to the string I passed into the function, the contents of the base64 data are being modified. I spend DAYS debugging this and finally wrote a test controller that passed the data in base64 to post and also took the name of a local file with the correct base64 encoded data, as in:

data=AAA-base-64-data...&testFilename=/name/of/file/with/base64data

内测试功能我比较与在测试文件中的相应字节的输入数据的参数的每一个字节。我发现,不知怎的,每一个+,在输入数据参数的性格已经被替换为(空格,ASCII码序号32)。咦?什么可以做呢?

Within the test function I compared every byte in the incoming data parameter with the appropriate byte in the test file. I found that somehow every "+" character in the input data parameter had been replaced with a " " (space, ordinal ascii 32). Huh? What could have done that?

要确定我是正确的,我加了一行说:

To be sure I was correct, I added a line that said:

data = data.replaceAll(' ', '+')

果然数据删除codeD分毫不差。我用任意长的二进制文件尝试过了,现在屡试不爽。但我想不出我的生活会有什么改变数据参数在后转换的ORD(43)字符为ord(32)?我知道,加号是为Base64规范的2有些依赖于平台的角色之一,但考虑到我做的编码和在同一台机器上,现在我超疑惑是什么原因造成这种解码。当然,我有一个修复,因为我可以让它工作,但我很担心修复,我不明白。

and sure enough the data decoded exactly right. I tried it with arbitrarily long binary files and it now works every time. But I can't figure out for the life of me what would be modifying the data parameter in the post to convert the ord(43) character to ord(32)? I know that the plus sign is one of the 2 somewhat platform dependent characters in the base64 spec, but given that I am doing the encoding and decoding on the same machine for now I am super puzzled what caused this. Sure I have a "fix" since I can make it work, but I am nervous about "fixes" that I don't understand.

在code是太大,张贴在这里,但我得到的base64编码像这样:

The code is too big to post here, but I get the base64 encoding like so:

def inputFile = new File(inputFilename)
def rawData =  inputFile.getBytes()
def encoded = rawData.encodeBase64().toString()

然后我写EN codeD串出新的文件中,以便以后我可以用它进行测试。如果我加载该文件早在如此我得到同样的RAWDATA:

I then write that encoded string out to new a file so I can use it for testing later. If I load that file back in as so I get the same rawData:

def encodedFile = new File(encodedFilename)
String encoded = encodedFile.getText()
byte[] rawData = encoded.decodeBase64()

因此​​,所有是好的。现在假设我走恩codeD变量,并把它添加到一个参数一个POST功能,像这样:

So all that is good. Now assume I take the "encoded" variable and add it to a param to a POST function like so:

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"
}

在Web服务端,在控制器中我得到的参数,像这样:

on the web service side, in the controller I get the parameter like so:

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()

很抱歉的长期的咆哮,但是我真的很想明白,为什么我不得不这样做用加号替换空间的得到这个去code正确。是否有一个请求参数被用于一些问题,加号?

Sorry for the long rant, but I'd really love to understand why I had to do the "replace space with plus sign" to get this to decode correctly. Is there some problem with the plus sign being used in a request parameter?

推荐答案

无论填充 PARAMS 预计请求一个URL-CN codeD形式(具体而言, 应用程序/ x-WWW的形式urlen codeD ,其中+表示空格),但你没有URL-CN code吧。我不知道哪些功能您的语言提供,但在伪code,的queryString

Whatever populates params expects the request to be a URL-encoded form (specifically, application/x-www-form-urlencoded, where "+" means space), but you didn't URL-encode it. I don't know what functions your language provides, but in pseudo code, queryString should be constructed from

concat(uri_escape("data"), "=", uri_escape(base64_encode(rawBytes)))

这简化为

concat("data=", uri_escape(base64_encode(rawBytes)))

+ 字符将被替换为%2B

这篇关于奇怪的Base64 EN code /德code问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆