【问题标题】:Swift base64 decoding returns nilSwift base64 解码返回 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())

标签: ios swift uiimage base64 decode


【解决方案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】:

    特殊字符会造成问题,但有趣的是,如果我们使用 NSDataNSString 则它​​工作正常。

    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)
              }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2016-12-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2022-01-14
              • 1970-01-01
              • 2018-01-29
              相关资源
              最近更新 更多