[英]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 问题,但与此无关。
请注意以下几点:
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 字符串
您必须“ append "="... 所以它可以被 4 整除”这一事实是一个很大的线索。 这意味着您的字符串格式不正确。
如果您检查字符串的长度(您在 GitHub 上发布的),您会看到它是65535
... 这也是0xFFFF
... 这也是16-bits
。
所以,听起来你的“API”没有返回完整的图像。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.