Как сказал Питер, заголовок типа контента - это просто "подсказка" о том, каким будет ожидаемый контент. На стороне сервера вы можете установить любой тип контента и отправить любые байтовые последовательности, которые могут быть недопустимыми.
У меня была точно такая же проблема, связанная с неверными данными UTF-8, которая включала символы ISO-8859-1 (Latin-1) (французские акценты).
Википедия о UTF-8 стоит прочитать, чтобы понять эту проблему и как справиться с ошибками кодирования.
Дело в том, что NSString initWithData:encoding:
строгая реализация просто возвращает ноль, когда происходит ошибка декодирования. (в отличие от java, например, который использует символ замены)
Решение Питера по преобразованию в основном данных UTF-8 в Latin-1 меня не удовлетворяло.
(Все символы UTF-8 становятся неправильными, только для одного латинского 1 ошибочного символа)
Лучшим вариантом будет исправление на стороне сервера, конечно, но я не несу ответственности за эту сторону ...
Итак, я посмотрел глубже и нашел решение, используя библиотеку GNU libiconv C (доступна для OSX и iOS).
Принцип заключается в использовании iconv для удаления недопустимых символов, не относящихся к UTF-8 (т. Е. «Prété» станет «prt»)
Вот пример кода, эквивалентный командной строке iconv -c -f UTF-8 -t UTF-8 invalid.txt > cleaned.txt
#include "iconv.h"
- (NSData *)cleanUTF8:(NSData *)data {
iconv_t cd = iconv_open("UTF-8", "UTF-8"); // convert to UTF-8 from UTF-8
int one = 1;
iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, &one); // discard invalid characters
size_t inbytesleft, outbytesleft;
inbytesleft = outbytesleft = data.length;
char *inbuf = (char *)data.bytes;
char *outbuf = malloc(sizeof(char) * data.length);
char *outptr = outbuf;
if (iconv(cd, &inbuf, &inbytesleft, &outptr, &outbytesleft)
== (size_t)-1) {
NSLog(@"this should not happen, seriously");
return nil;
}
NSData *result = [NSData dataWithBytes:outbuf length:data.length - outbytesleft];
iconv_close(cd);
free(outbuf);
return result;
}
Затем полученный NSData
можно безопасно декодировать, используя NSUTF8StringEncoding
Обратите внимание, что последние iconv также позволяют использовать запасные методы, используя:
iconvctl(cd, ICONV_SET_FALLBACKS, &fallbacks);
Используя запасной вариант при ошибках Юникода, вы можете использовать заменяющий символ или, что лучше, попробовать другую кодировку.
В моем случае мне удалось откатиться до LATIN-1, где произошел сбой UTF-8, что привело к 99% положительным конверсиям. Посмотрите на исходный код iconv, чтобы понять его.