从 API 调用返回的 base64encoded 字符串在 Data(base64encoded: data) 为 运行 后显示为 nil

base64encoded string returned from API call is showing nil after Data(base64encoded: data) is ran

我对此很困惑。我一直认为我的服务器有问题,但在测试之后似乎使用 Data(base64encoded: data) 产生了 nil,即使数据在那里并且实际上是 base64 编码的。 我已经尝试了我能想到的一切,但没有任何效果。这是我正在使用的代码和输出...

do {
  print("DATA as a string: ", String(data: data!, encoding: .utf8) ?? "NONE AVAILABLE")
  let decodedData = Data(base64encoded: data!, options: .ignoreUnknownCharacters)
  print("DECODED DATA: ")
  print(decodedData as Any)
  let apiResponse = try JSONDecoder().decode(ApiConnectionResponse.self, from: decodedData!)
  completion(.success(apiResponse))
} catch {
  completion(.failure(error))
}

输出是...

Data as string: eyJzdWNjZXNzIjoiZmFsc2UiLCJlcnJvciI6Im1vYmlsZV9waW5fY29ubmVjdDogaW52YWxpZCBvciBleHBpcmVkIn0.

DECODED DATA: nil

所以字符串是合法的 base64 编码字符串,它解码为

{"success":"false","error":"mobile_pin_connect: invalid or expired"}

然而解码数据为零。我不明白,当字符串是base64编码的字符串而不是nil时,怎么会是nil。 我什至试过像这样强行插入字符串...

let decodedData = Data(base64encoded: String(data: data!, encoding: .utf8))

仍然没有运气。它抛出一个致命错误,我可以在 Xcode 底部的部分看到数据实际上是“(数据?)92 字节”我不明白的是为什么它在之后是 nil 运行 通过数据 ()...

任何帮助将不胜感激,我真的迷路了,想不通为什么我可以制作字符串,但不能制作数据。

最终结果是,我需要获取 JSONDecoder().decode 来处理来自服务器的回复,我想我可以完成这部分,如果我能弄清楚为什么它在数据通话。谢谢。

估计编码数据有误

let originalString = """
{"success":"false","error":"mobile_pin_connect: invalid or expired"}
"""

let base64string = originalString.data(using: .utf8)?.base64EncodedString()
print(base64string)

let base64EncodedData = originalString.data(using: .utf8)?.base64EncodedData()
let base64EncodedString = String(data: base64EncodedData!, encoding: .utf8)
print(base64EncodedString)

let decodedData = Data(base64Encoded: base64EncodedData!)
let decodedString = String(data: decodedData!, encoding: .utf8)
print(decodedString)

日志如下:

Optional("eyJzdWNjZXNzIjoiZmFsc2UiLCJlcnJvciI6Im1vYmlsZV9waW5fY29ubmVjdDogaW52YWxpZCBvciBleHBpcmVkIn0=")
Optional("eyJzdWNjZXNzIjoiZmFsc2UiLCJlcnJvciI6Im1vYmlsZV9waW5fY29ubmVjdDogaW52YWxpZCBvciBleHBpcmVkIn0=")
Optional("{\"success\":\"false\",\"error\":\"mobile_pin_connect: invalid or expired\"}")

根据 base64 规范,. 不是有效字符。 = 是适合填充的字符。

https://en.wikipedia.org/wiki/Base64

您需要检查您的数据长度,除以 3,如果结果不为零,则添加一个或两个字节 (65) = 等号来填充您的数据。像这样尝试:

let decodedData = Data(base64Encoded: data + .init(repeating: 65, count: data.count % 3))

extension Data {
    var base64encodedDataPadded: Data {
        let data = last == 46 ? dropLast() : self
        return data + .init(repeating: 65, count: data.count % 3)
    }
}

游乐场测试:

let data = Data("eyJzdWNjZXNzIjoiZmFsc2UiLCJlcnJvciI6Im1vYmlsZV9waW5fY29ubmVjdDogaW52YWxpZCBvciBleHBpcmVkIn0.".utf8)
let decodedData = Data(base64Encoded: data.base64encodedDataPadded)!
print(String(data: decodedData, encoding: .utf8)!) // "{"success":"false","error":"mobile_pin_connect: invalid or expired"}"

您将 base64 字符串显示为末尾有一个句点和一个换行符。这看起来不正确。一个在线 base64 解码器在有或没有最后的句号和换行符的情况下对其进行解码,但 Swift 可能会在适当的位置窒息。