简体   繁体   English

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

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

I have an iOS app that gets an image as a base64 encoded string from an API.我有一个 iOS 应用程序,它从 API 获取图像作为base64编码字符串。 (I know that maybe it's not the best solution, but that not the question). (我知道这可能不是最好的解决方案,但这不是问题)。

When I decode this string to create an UIImage with the following code:当我解码此字符串以使用以下代码创建 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 )

The returned image is cropped (I added the red background just for developing purposes):返回的图像被裁剪(我添加了红色背景只是为了开发目的):

在此处输入图像描述

As you can see I get an error saying that "Failed to convert UIImage to PNG" .如您所见,我收到一条错误消息,提示“无法将 UIImage 转换为 PNG”


So at this point I started to think that maybe there was a mistake in my code.所以此时我开始认为我的代码可能有错误。 Maybe I was getting an incomplete string or the was some missing step in the decoding.也许我得到了一个不完整的字符串,或者解码中缺少一些步骤。 So I asked the backend guy and he confirmed me that the string was correct.所以我问了后端的人,他确认我的字符串是正确的。 Also I checked with my colleague who works on the Android version and the same string works properly in his app.我还与使用 Android 版本的同事进行了核对,并且相同的字符串在他的应用程序中正常工作。

So I tested the string in an online decoder and I founded the same cropped result using Safari Versión 13.0.5 (15608.5.11), but the full image using Firefox :因此,我在在线解码器中测试了字符串,并使用Safari版本 13.0.5 (15608.5.11) 创建了相同的裁剪结果,但使用Firefox完整图像:

在此处输入图像描述 WTF !

I tested it with the same result in several web decoders:我在几个 web 解码器中对其进行了测试,结果相同:

OK, so I tried to download the image from Firefox and try to encode/decode it myself, but surprise.好的,所以我尝试从 Firefox 下载图像并尝试自己对其进行编码/解码,但令人惊讶。 I can see the image but I can't download it complete on my Mac.我可以看到图像,但无法在我的 Mac 上完整下载。

在此处输入图像描述 This are the images downloaded from Firefox in png and jpg这是从 Firefox 下载的 png 和 jpg 格式的图像

I've been trying to find a solution in google and several forums, including a lot of StackOverflow questions, but nothing related to this.我一直试图在谷歌和几个论坛中找到解决方案,包括很多 StackOverflow 问题,但与此无关。

Please notice the following points:请注意以下几点:

  • The returned decode data is not nil .返回的解码数据不是 nil I'm appending "=" characters at the end of the string to ensure that the string length % 4 == 0 .I've found a lot of questions about that problem, I am able to decode the image, but cropped.我在字符串末尾附加了“=”字符以确保字符串长度 % 4 == 0 。我发现了很多关于这个问题的问题,我能够解码图像,但是被裁剪了。
  • I'm 100% sure that the string is complete, I've checked it with my backend and android colleagues.我 100% 确定字符串是完整的,我已经与我的后端和 android 同事检查了它。
  • It seems to be a problem related to the Apple environment, I can't see the image in my iOS app neither in Safari, but I can see it in Firefox running on a Mac Computer.这似乎是与 Apple 环境相关的问题,我在 Safari 中都看不到我的 iOS 应用程序中的图像,但我可以在 Firefox 中看到它在 Mac 计算机上运行。 Also it's not happening only in my computer.而且它不仅仅发生在我的电脑上。 Some other colleagues tested in their iPhones with same result.其他一些同事在他们的 iPhone 上进行了测试,结果相同。

The base64 string is REALLY LONG (I'll pasting it below). base64 字符串真的很长(我将在下面粘贴)。 So I tried to decode half of the string just to be sure that the problem was not related with the size and I've found something curios.所以我尝试解码一半的字符串,以确保问题与大小无关,并且我发现了一些古玩。 If I decode just half of the string I also get the result cropped:如果我只解码字符串的一半,我也会得到裁剪的结果:

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

在此处输入图像描述

I don't know if this approximation is correct but I tried it.我不知道这个近似值是否正确,但我试过了。


I tried to find a solution using an Objective-C function but the result was the same:我尝试使用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;
}

So at this point I'm completely lost.所以在这一点上我完全迷路了。 Why this is happening?为什么会这样?

And here it is the damm base64 String这是该死的 base64 字符串

THE DAMM STRING AT GITHUB GITHUB 处的 DAMM 字符串

The fact that you had to " append "="... so it would be evenly divisible by 4 " is a big clue.您必须“ append "="... 所以它可以被 4 整除”这一事实是一个很大的线索。 That means your string is formatted incorrectly.这意味着您的字符串格式不正确。

If you check the length of your string (that you posted at GitHub), you'll see it is 65535 ... which is also 0xFFFF ... which is also 16-bits .如果您检查字符串的长度(您在 GitHub 上发布的),您会看到它是65535 ... 这也是0xFFFF ... 这也是16-bits

So, it sounds like your "API" is not returning the complete image.所以,听起来你的“API”没有返回完整的图像。

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

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