Swift base64 解码返回 nil
Posted
技术标签:
【中文标题】Swift base64 解码返回 nil【英文标题】:Swift base64 decoding returns nil 【发布时间】:2016-07-21 17:34:20 【问题描述】:我正在尝试使用以下代码将 base64 字符串解码为 Swift 中的图像:
let decodedData=NSData(base64EncodedString: encodedImageData, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
不幸的是,变量 decodedData 的值为 nil
通过代码调试,我验证了变量 encodedImageData 不是 nil 并且是正确的编码图像数据(通过使用在线 base64 到图像转换器进行验证)。我的问题背后的原因可能是什么?
【问题讨论】:
您尝试过基本选项吗?let decodedData=NSData(base64EncodedString: encodedImageData, options: NSDataBase64EncodingOptions())
【参考方案1】:
这对我有帮助:
extension String
func fromBase64() -> String?
guard let data = Data(base64Encoded: self.replacingOccurrences(of: "_", with: "="), options: Data.Base64DecodingOptions(rawValue: 0)) else
return nil
return String(data: data, encoding: .utf8)
用法:
print(base64EncodedString.fromBase64())
【讨论】:
【参考方案2】:特殊字符会造成问题,但有趣的是,如果我们使用 NSData 和 NSString 则它工作正常。
static func decodeBase64(input: String)->String
let base64Decoded = NSData(base64Encoded: input, options: NSData.Base64DecodingOptions(rawValue: 0))
.map( NSString(data: $0 as Data, encoding: String.Encoding.utf8.rawValue) )
return base64Decoded!! as String
【讨论】:
【参考方案3】:检查您的 decodedData 变量的内容并查找此前缀“data:image/png;base64”,我遇到了这个问题,并注意到我的 String base64 有一个这样的前缀,所以我使用了这个方法并且它有效
extension String
func getImageFromBase64() -> UIImage?
guard let url = URL(string: self) else
return nil
do
let data = try Data(contentsOf: url)
return UIImage(data: data)
catch
return nil
【讨论】:
【参考方案4】:此方法需要用“=”填充,字符串的长度必须是4的倍数。
在 base64 的某些实现中,解码不需要填充字符,因为可以计算丢失的字节数。但在 Fundation 的实施中,这是强制性的。
更新: 如 cmets 所述,最好先检查字符串长度是否已经是 4 的倍数。如果 encoded64 具有您的 base64 字符串并且它不是常量,您可以执行以下操作:
斯威夫特 2
let remainder = encoded64.characters.count % 4
if remainder > 0
encoded64 = encoded64.stringByPaddingToLength(encoded64.characters.count + 4 - remainder,
withPad: "=",
startingAt: 0)
斯威夫特 3
let remainder = encoded64.characters.count % 4
if remainder > 0
encoded64 = encoded64.padding(toLength: encoded64.characters.count + 4 - remainder,
withPad: "=",
startingAt: 0)
斯威夫特 4
let remainder = encoded64.count % 4
if remainder > 0
encoded64 = encoded64.padding(toLength: encoded64.count + 4 - remainder,
withPad: "=",
startingAt: 0)
更新了一行版本:
或者你可以使用这一行版本,当它的长度已经是 4 的倍数时返回相同的字符串:
encoded64.padding(toLength: ((encoded64.count+3)/4)*4,
withPad: "=",
startingAt: 0)
【讨论】:
对于长度已经是 4 的倍数的字符串,您的代码会添加四个不必要的 '='! @Mbt925 在这里,我向 OP 解释为什么 base64 解码可能会失败。当然,先检查一下你的字符串长度是否已经是 4 的倍数也不错。我借此机会更新到 swift 3。 我最终使用:encoded64 = encoded64.padding(toLength: encoded64.characters.count + (4 - remainder) % 4, withPad: "=", startingAt: 0)
没有if
。
@Mbt925 我已经用另一行版本更新了答案,考虑到长度可能已经是 4 的倍数。
用“=”填充目前似乎被破坏了。我建议用“A”填充,这确实有效。已经提交了一个错误。【参考方案5】:
(斯威夫特 3) 我遇到过这种情况,当我使用这一行时,尝试使用 base64 编码的字符串获取数据返回 nil
let imageData = Data(base64Encoded: strBase64, options: .ignoreUnknownCharacters)
尝试填充字符串,但也没有成功
这对我有用
func imageForBase64String(_ strBase64: String) -> UIImage?
do
let imageData = try Data(contentsOf: URL(string: strBase64)!)
let image = UIImage(data: imageData)
return image!
catch
return nil
【讨论】:
【参考方案6】:另一个单行版本:
let length = encoded64.characters.count
encoded64 = encoded64.padding(toLength: length + (4 - length % 4) % 4, withPad: "=", startingAt: 0)
【讨论】:
【参考方案7】:当字符数能被4整除时,需要避免填充。
private func base64PaddingWithEqual(encoded64: String) -> String
let remainder = encoded64.characters.count % 4
if remainder == 0
return encoded64
else
// padding with equal
let newLength = encoded64.characters.count + (4 - remainder)
return encoded64.stringByPaddingToLength(newLength, withString: "=", startingAtIndex: 0)
【讨论】:
以上是关于Swift base64 解码返回 nil的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Web 获取 base64 并在 Swift 中解码?
Swift 中的 Base64 编码不会在 Android 中解码
Swift Decodable - 如何解码经过 base64 编码的嵌套 JSON