Почему при декодировании текстовой строки base64 на устройстве Apple появляется обрезанное изображение? - PullRequest
1 голос
/ 21 апреля 2020

У меня есть приложение iOS, которое получает изображение в виде строки в кодировке base64 из API. (Я знаю, что, возможно, это не лучшее решение, но это не вопрос).

Когда я декодирую эту строку, чтобы создать UIImage со следующим кодом:

// If don't don't append "=" I'll get nil data in the next line: (string.count % 4 == 0) is required
    let stringWithEquals:String = getMyString() + "=" 
    let data = Data.init(base64Encoded: stringWithEquals, options: .ignoreUnknownCharacters)!
    self.myPicture.image = UIImage(data: data )

Возвращенный изображение обрезано (я добавил красный фон только для развивающих целей):

enter image description here

Как видите, я получаю ошибка, говорящая о том, что «Не удалось преобразовать UIImage в PNG» .


Поэтому в этот момент я начал думать, что, возможно, в моем коде произошла ошибка. Возможно, я получил неполную строку или был какой-то недостающий шаг в декодировании. Поэтому я спросил бэкэнда, и он подтвердил, что строка верна. Также я проверил со своим коллегой, который работает над версией Android, и та же строка правильно работает в его приложении.

Итак, я проверил строку в онлайн-декодере и нашел тот же обрезанный результат использования Safari Версия 13.0.5 (15608.5.11), но полное изображение с использованием Firefox:

enter image description here WTF !

Я тестировал его с одинаковым результатом на нескольких веб-декодерах:

ОК, поэтому я попытался загрузить изображение с Firefox и попробуй сам кодировать / декодировать, но удиви! Я вижу изображение, но не могу загрузить его полностью на моем Ма c.

enter image description here Это изображения, загруженные с Firefox в png и jpg

Я пытался найти решение в Google и на нескольких форумах, включая множество вопросов о StackOverflow, но с этим ничего не связано.

Обратите внимание на следующие моменты:

  • Возвращенные данные декодирования не равны . Я добавляю символы «=» в конце строки, чтобы длина строки% 4 == 0 . Я нашел много вопросов по этой проблеме, я могу декодировать изображение, но обрезано.
  • Я на 100% уверен, что строка завершена, я проверил ее с моим бэкэндом и android коллегами.
  • Кажется, проблема связана с в среде Apple я не вижу изображения в своем приложении iOS ни в Safari, но вижу в Firefox, работающем на компьютере Ma c. Также это происходит не только на моем компьютере. Некоторые другие коллеги тестировали в своих iPhone с таким же результатом.

Строка base64 действительно длинная (я вставлю ее ниже). Поэтому я попытался декодировать половину строки, просто чтобы убедиться, что проблема не связана с размером, и я нашел что-то cur ios. Если я декодирую только половину строки, я также получаю обрезанный результат:

    let stringWithEquals:String = getMyString().prefix(getMyString().count/2) + "="

enter image description here

Я не знаю, правильное ли это приближение, но Я попробовал.


Я пытался найти решение, используя функцию Objective- C, но результат был таким же:

-(NSData *)base64DataFromString: (NSString *)string{
    unsigned long ixtext, lentext;
    unsigned char ch, inbuf[4], outbuf[3];
    short i, ixinbuf;
    Boolean flignore, flendtext = false;
    const unsigned char *tempcstring;
    NSMutableData *theData;

    if (string == nil){
        return [NSData data];
    }

    ixtext = 0;

    tempcstring = (const unsigned char *)[string UTF8String];

    lentext = [string length];

    theData = [NSMutableData dataWithCapacity: lentext];

    ixinbuf = 0;

    while (true){
        if (ixtext >= lentext){
            break;
        }
        ch = tempcstring [ixtext++];

        flignore = false;

        if ((ch >= 'A') && (ch <= 'Z')){
            ch = ch - 'A';
        }else if ((ch >= 'a') && (ch <= 'z')){
            ch = ch - 'a' + 26;
        }else if ((ch >= '0') && (ch <= '9')){
            ch = ch - '0' + 52;
        }else if (ch == '+'){
            ch = 62;
        }else if (ch == '='){
            flendtext = true;
        }else if (ch == '/'){
            ch = 63;
        }else{
            flignore = true;
        }

        if (!flignore){
            short ctcharsinbuf = 3;
            Boolean flbreak = false;

            if (flendtext){
                if (ixinbuf == 0){
                    break;
                }
                if ((ixinbuf == 1) || (ixinbuf == 2)){
                    ctcharsinbuf = 1;
                }else{
                    ctcharsinbuf = 2;
                }
                ixinbuf = 3;

                flbreak = true;
            }

            inbuf [ixinbuf++] = ch;

            if (ixinbuf == 4){
                ixinbuf = 0;

                outbuf[0] = (inbuf[0] << 2) | ((inbuf[1] & 0x30) >> 4);
                outbuf[1] = ((inbuf[1] & 0x0F) << 4) | ((inbuf[2] & 0x3C) >> 2);
                outbuf[2] = ((inbuf[2] & 0x03) << 6) | (inbuf[3] & 0x3F);

                for (i = 0; i < ctcharsinbuf; i++){
                    [theData appendBytes: &outbuf[i] length: 1];
                }
            }

            if (flbreak){
                break;
            }
        }
    }
    return theData;
}

Итак на данный момент я полностью потерян. Почему это происходит?

А вот и дамба base64 Строка

СТРЕЛА ДАММА НА ГИТУБЕ

1 Ответ

0 голосов
/ 21 апреля 2020

Тот факт, что вам нужно было " append" = "... чтобы оно могло быть равномерно разделено на 4 ", является большой подсказкой. Это означает, что ваша строка отформатирована неправильно.

Если вы проверите длину вашей строки (которую вы разместили на GitHub), вы увидите, что она равна 65535 ..., что также 0xFFFF .. ... который также 16-bits.

Итак, похоже, что ваш "API" не возвращает полное изображение.

...