Я пытаюсь загрузить бинарный файл, используя XMLHttpRequest
(используя недавний Webkit), и base64-закодировать его содержимое с помощью этой простой функции:
function getBinary(file){
var xhr = new XMLHttpRequest();
xhr.open("GET", file, false);
xhr.overrideMimeType("text/plain; charset=x-user-defined");
xhr.send(null);
return xhr.responseText;
}
function base64encode(binary) {
return btoa(unescape(encodeURIComponent(binary)));
}
var binary = getBinary('http://some.tld/sample.pdf');
var base64encoded = base64encode(binary);
В качестве примечания, все вышеперечисленное является стандартным Javascript, включая btoa()
и encodeURIComponent()
: https://developer.mozilla.org/en/DOM/window.btoa
Это работает довольно гладко, и я даже могу декодировать содержимое base64, используя Javascript:
function base64decode(base64) {
return decodeURIComponent(escape(atob(base64)));
}
var decodedBinary = base64decode(base64encoded);
decodedBinary === binary // true
Теперь я хочу декодировать содержимое в кодировке base64, используя Python, который использует некоторую строку JSON для получения строкового значения base64encoded
. Наивно вот что я делаю:
import urllib
import base64
# ... retrieving of base64 encoded string through JSON
base64 = "77+9UE5HDQ……………oaCgA="
source_contents = urllib.unquote(base64.b64decode(base64))
destination_file = open(destination, 'wb')
destination_file.write(source_contents)
destination_file.close()
Но полученный файл неверен, похоже, что операция испорчена UTF-8, кодировкой или чем-то, что мне до сих пор неясно.
Если я пытаюсь декодировать содержимое UTF-8 перед тем, как поместить его в файл назначения, возникает ошибка:
import urllib
import base64
# ... retrieving of base64 encoded string through JSON
base64 = "77+9UE5HDQ……………oaCgA="
source_contents = urllib.unquote(base64.b64decode(base64)).decode('utf-8')
destination_file = open(destination, 'wb')
destination_file.write(source_contents)
destination_file.close()
$ python test.py
// ...
UnicodeEncodeError: 'ascii' codec can't encode character u'\ufffd' in position 0: ordinal not in range(128)
В качестве примечания приведен скриншот двух текстовых представлений одного и того же файла; слева: оригинал; справа: тот, который создан из строки, декодированной base64: http://cl.ly/0U3G34110z3c132O2e2x
Есть ли известная уловка, позволяющая обойти эти проблемы с кодировкой при попытке воссоздания файла? Как бы вы этого добились?
Любая помощь или подсказка высоко ценится:)