web-dev-qa-db-ja.com

Swift base64デコードはnilを返します

次のコードを使用して、base64文字列をSwiftの画像にデコードしようとしています:

let decodedData=NSData(base64EncodedString: encodedImageData, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)

残念ながら、変数decodeDataの値はnilであることが判明しました

コードをデバッグして、変数encodedImageDataがnilではなく、正しいエンコードされた画像データであることを確認しました(オンラインのbase64から画像へのコンバーターを使用して確認しました)。私の問題の背後にある理由は何でしょうか?

16
redamakarem

この方法では、「=」でパディングする必要があり、文字列の長さは4の倍数である必要があります。

Base64の一部の実装では、欠落しているバイト数を計算できるため、デコードにパディング文字は必要ありません。しかし、Fundationの実装では、それは必須です。

更新:コメントに記載されているように、文字列の長さがすでに4の倍数であるかどうかを最初に確認することをお勧めします。ifencoded64base64文字列があり、定数ではありません。次のように実行できます。

スウィフト2

let remainder = encoded64.characters.count % 4
if remainder > 0 {
    encoded64 = encoded64.stringByPaddingToLength(encoded64.characters.count + 4 - remainder,
                                                  withPad: "=",
                                                  startingAt: 0)
}

Swift

let remainder = encoded64.characters.count % 4
if remainder > 0 {
    encoded64 = encoded64.padding(toLength: encoded64.characters.count + 4 - remainder,
                                  withPad: "=",
                                  startingAt: 0)
}

Swift 4

let remainder = encoded64.count % 4
if remainder > 0 {
    encoded64 = encoded64.padding(toLength: encoded64.count + 4 - remainder,
                                  withPad: "=",
                                  startingAt: 0)
}

1行バージョンを更新:

または、長さがすでに4の倍数である場合に同じ文字列を返すこの1行バージョンを使用できます。

encoded64.padding(toLength: ((encoded64.count+3)/4)*4,
                  withPad: "=",
                  startingAt: 0)
34
jlasierra

文字数が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)
  }
}
5
k-yamada

(Swift 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
    }
}
2

デコードされたデータ変数の内容を確認し、このプレフィックス「data:image/png; base64」を探します。この問題が発生し、文字列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
    }

}

}

0
Joule87

特殊文字で問題が発生しますが、興味深い点は、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
}
0

別の1行バージョン:

let length = encoded64.characters.count
encoded64 = encoded64.padding(toLength: length + (4 - length % 4) % 4, withPad: "=", startingAt: 0)
0
Mbt925