繁体   English   中英

为什么在 Apple 设备上解码 base64 文本字符串时会看到裁剪的图像?

[英]Why am I seeing a cropped image when decoding a base64 text string on an Apple device?

我有一个 iOS 应用程序,它从 API 获取图像作为base64编码字符串。 (我知道这可能不是最好的解决方案,但这不是问题)。

当我解码此字符串以使用以下代码创建 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 )

返回的图像被裁剪(我添加了红色背景只是为了开发目的):

在此处输入图像描述

如您所见,我收到一条错误消息,提示“无法将 UIImage 转换为 PNG”


所以此时我开始认为我的代码可能有错误。 也许我得到了一个不完整的字符串,或者解码中缺少一些步骤。 所以我问了后端的人,他确认我的字符串是正确的。 我还与使用 Android 版本的同事进行了核对,并且相同的字符串在他的应用程序中正常工作。

因此,我在在线解码器中测试了字符串,并使用Safari版本 13.0.5 (15608.5.11) 创建了相同的裁剪结果,但使用Firefox完整图像:

在此处输入图像描述

我在几个 web 解码器中对其进行了测试,结果相同:

好的,所以我尝试从 Firefox 下载图像并尝试自己对其进行编码/解码,但令人惊讶。 我可以看到图像,但无法在我的 Mac 上完整下载。

在此处输入图像描述 这是从 Firefox 下载的 png 和 jpg 格式的图像

我一直试图在谷歌和几个论坛中找到解决方案,包括很多 StackOverflow 问题,但与此无关。

请注意以下几点:

  • 返回的解码数据不是 nil 我在字符串末尾附加了“=”字符以确保字符串长度 % 4 == 0 。我发现了很多关于这个问题的问题,我能够解码图像,但是被裁剪了。
  • 我 100% 确定字符串是完整的,我已经与我的后端和 android 同事检查了它。
  • 这似乎是与 Apple 环境相关的问题,我在 Safari 中都看不到我的 iOS 应用程序中的图像,但我可以在 Firefox 中看到它在 Mac 计算机上运行。 而且它不仅仅发生在我的电脑上。 其他一些同事在他们的 iPhone 上进行了测试,结果相同。

base64 字符串真的很长(我将在下面粘贴)。 所以我尝试解码一半的字符串,以确保问题与大小无关,并且我发现了一些古玩。 如果我只解码字符串的一半,我也会得到裁剪的结果:

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

在此处输入图像描述

我不知道这个近似值是否正确,但我试过了。


我尝试使用Objective-C function 找到解决方案,但结果是相同的:

-(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 字符串

GITHUB 处的 DAMM 字符串

您必须“ append "="... 所以它可以被 4 整除”这一事实是一个很大的线索。 这意味着您的字符串格式不正确。

如果您检查字符串的长度(您在 GitHub 上发布的),您会看到它是65535 ... 这也是0xFFFF ... 这也是16-bits

所以,听起来你的“API”没有返回完整的图像。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM