Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 为什么在苹果设备上解码base64文本字符串时,我会看到一个裁剪过的图像?_Ios_Objective C_Swift_Macos_Safari - Fatal编程技术网

Ios 为什么在苹果设备上解码base64文本字符串时,我会看到一个裁剪过的图像?

Ios 为什么在苹果设备上解码base64文本字符串时,我会看到一个裁剪过的图像?,ios,objective-c,swift,macos,safari,Ios,Objective C,Swift,Macos,Safari,我有一个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() + "="

我有一个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创建了完整图像:

WTF

我在几个web解码器中测试了它,结果相同:

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

这是以png和jpg格式从Firefox下载的图像

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

请注意以下几点:

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

base64字符串非常长(我将在下面粘贴它)。所以我试着解码字符串的一半,只是为了确定问题与大小无关,我发现了一些古玩。如果我只解码了字符串的一半,结果也会被裁剪:

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

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


我尝试使用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;
}
-(NSData*)base64DataFromString:(NSString*)string{
无符号长文本,lentext;
无符号字符ch,inbuf[4],extruf[3];
短i,ixinbuf;
布尔flignore,flendtext=false;
常量无符号字符*临时字符串;
n可变数据*数据;
如果(字符串==nil){
返回[NSData data];
}
ixtext=0;
tempcstring=(const unsigned char*)[string UTF8String];
lentext=[字符串长度];
数据=[NSMutableData dataWithCapacity:lentext];
ixinbuf=0;
while(true){
如果(ixtext>=lentext){
打破
}
ch=tempcstring[ixtext++];
flignore=false;
如果((ch>='A')&&(ch='A')&&(ch='0')&&(ch 4);
exputf[1]=((inbuf[1]&0x0F)>2);
exputf[2]=((inbuf[2]&0x03)您必须“附加”=“…这样它就可以被4整除,这是一个很好的线索。这意味着您的字符串格式不正确

如果您检查字符串的长度(您在GitHub发布的),您将看到它是
65535
…这也是
0xFFFF
…这也是
16位

因此,听起来您的“API”没有返回完整的图像。

您必须“附加”=“…这样它就可以被4整除,这是一个很好的线索。这意味着您的字符串格式不正确

如果您检查字符串的长度(您在GitHub发布的),您将看到它是
65535
…这也是
0xFFFF
…这也是
16位


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

但是为什么我可以在Firefox中使用相同的字符串来查看完整图像?我的意思是,我只是复制粘贴相同的字符串,然后works@Leemur-你能将你的原始图像添加到你的问题中吗?也许Safari的最大粘贴长度为65535个字符,而Firefox没有?GITHUB的DAMM字符串是截断的d、 也是。这不是完整图像的base64编码。请询问您的后端人员他的字符串是否为65535字节。但是为什么我可以在Firefox中使用相同的字符串来查看完整图像?我的意思是,我只是复制粘贴相同的字符串,并且works@Leemur-能否将原始图像添加到问题中?Safari的最大粘贴长度可能为65535个字符rs和Firefox没有?GITHUB上的DAMM字符串也被截断了。它不是完整图像的base64编码。询问后端人员他的字符串是否为65535字节。