我使用Grails 1.3.7.我有一些代码使用内置的base64Encode函数和base64Decode函数.在一些简单的测试用例中,一切都可以正常工作,在这些情况下,我会对一些二进制数据进行编码,然后解码生成的字符串并将其写入一个在这种情况下,文件是相同的.
但是后来我写了一个Web服务,将base64编码的数据作为POST调用中的一个参数.尽管base64数据的长度与传入函数的字符串相同,但是base64数据的内容正在被修改.我花了DAYS调试这个,最后写了一个测试控制器,它将base64中的数据传递给post,并且使用正确的base64编码数据的本地文件的名称,如:
data=AAA-base-64-data...&testFilename=/name/of/file/with/base64data
在测试函数中,我将输入数据参数中的每个字节与测试文件中的相应字节进行了比较.我发现输入数据参数中的每个“”字符都被替换为“”(空格,序号ascii 32).咦?该怎么办?
为了确定我是对的,我补充说:
data = data.replaceAll(' ','+')
并且确切地说,数据解码完全正确.我尝试了任意长的二进制文件,它现在每次都工作.但是,我不知道我的生活中将修改post的数据参数将ord(43)字符转换为ord(32)?我知道这个加号是base64规格中两个有点依赖平台的字符之一,但是由于我现在在同一台机器上进行编码和解码,所以我对此造成了很大的困惑.当然我有一个“修复”,因为我可以使它的工作,但我很紧张的“修复”,我不明白.
代码太大,不能在这里发布,但是我得到base64编码如下:
def inputFile = new File(inputFilename) def rawData = inputFile.getBytes() def encoded = rawData.encodeBase64().toString()
然后我将编码的字符串写入新的文件,以便稍后使用它进行测试.如果我加载该文件,所以我得到相同的rawData:
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" }
在Web服务端,在控制器中我得到如下参数:
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()
对不起长期的咆哮,但我真的很想明白为什么我必须做“替换空格加号”,以使其正确解码.请求参数中使用的加号有什么问题吗?