online imagen funciona decodificar decodificando como codificar codificando btoa html grails encoding groovy base64

html - imagen - decodificar base64 javascript



Extraño Base64 codifica/decodifica problema (4)

Estoy usando Grails 1.3.7. Tengo algún código que utiliza la función incorporada en base64Encode y la función base64Decode. Todo funciona bien en casos de prueba simples donde codifico algunos datos binarios y luego decodifico la cadena resultante y la escribo en un nuevo archivo. En este caso los archivos son idénticos.

Pero luego escribí un servicio web que tomó los datos codificados en base64 como un parámetro en una llamada POST. Aunque la longitud de los datos de base64 es idéntica a la cadena que pasé a la función, los contenidos de los datos de base64 se están modificando. Pasé los DÍAS depurando esto y finalmente escribí un controlador de prueba que pasó los datos en base64 para publicar y también tomó el nombre de un archivo local con los datos codificados en base64 correctos, como en:

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

Dentro de la función de prueba comparé cada byte en el parámetro de datos entrantes con el byte apropiado en el archivo de prueba. Encontré que, de alguna manera, todos los caracteres "+" en el parámetro de datos de entrada habían sido reemplazados por un "" (espacio, ordinal ascii 32). Eh ¿Qué podría haber hecho eso?

Para estar seguro de que estaba en lo cierto, agregué una línea que decía:

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

y efectivamente, los datos decodificados exactamente a la derecha. Lo intenté con archivos binarios arbitrariamente largos y ahora funciona siempre. Pero no puedo entender de por vida lo que sería modificar el parámetro de datos en la publicación para convertir el carácter ord (43) a ord (32)? Sé que el signo más es uno de los 2 caracteres algo dependientes de la plataforma en la especificación de base64, pero dado que estoy haciendo la codificación y la decodificación en la misma máquina, por ahora estoy muy confundido por lo que causó esto. Claro que tengo una "solución" ya que puedo hacer que funcione, pero estoy nervioso por las "soluciones" que no entiendo.

El código es demasiado grande para publicarlo aquí, pero obtengo la codificación base64 así:

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

Luego escribo esa cadena codificada en un nuevo archivo para poder usarlo para realizar pruebas más tarde. Si vuelvo a cargar ese archivo, obtendré el mismo rawData:

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

Así que todo eso es bueno. Ahora supongamos que tomo la variable "codificada" y la agrego a un parámetro a una función POST así:

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

en el lado del servicio web, en el controlador obtengo el parámetro así:

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

Lo siento por la perorata larga, pero me encantaría entender por qué tuve que hacer "reemplazar el espacio con el signo más" para que esto se descodifique correctamente. ¿Hay algún problema con el signo más que se utiliza en un parámetro de solicitud?



Lo que sea que params los params espera que la solicitud sea un formulario codificado en URL (específicamente, application/x-www-form-urlencoded , donde "+" significa espacio), pero no lo codificó con URL. No sé qué funciones proporciona su idioma, pero en pseudo código, queryString debe construirse a partir de

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

lo que simplifica a

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

Los caracteres " + " se reemplazarán con " %2B ".


Tienes que usar un código base64 especial que también es seguro para url. El problema es que el código base64 estándar incluye los caracteres + , / y = que se reemplazan por la versión codificada en porcentaje.

http://en.wikipedia.org/wiki/Base64#URL_applications

Estoy usando el siguiente código en PHP:

/** * Custom base64 encoding. Replace unsafe url chars * * @param string $val * @return string */ static function base64_url_encode($val) { return strtr(base64_encode($val), ''+/='', ''-_,''); } /** * Custom base64 decode. Replace custom url safe values with normal * base64 characters before decoding. * * @param string $val * @return string */ static function base64_url_decode($val) { return base64_decode(strtr($val, ''-_,'', ''+/='')); }


paraquote desde el enlace de wikipedia

La codificación utilizada de forma predeterminada se basa en una versión muy temprana de las reglas generales de codificación de porcentaje de URI, con una serie de modificaciones como la normalización de nueva línea y la sustitución de espacios con "+" en lugar de "% 20"

otro escollo oculto todos los desarrolladores web cotidianos como yo, sabemos poco