这个问题是关于在iOS 13中使用SwiftUI和Gmail API的DMARC报告查看器应用。报告是由google以xml格式邮寄到我们的管理员邮箱id,会被压缩。所以基本上它是一个压缩附件。所以在这里,GMail API被用来访问那些特定的邮件,使用过滤器,并从API中得到所有的base64编码数据。同时也将其解码为数据类型的数据。到此为止就可以了。下一部分是将字节格式的zip文件的数据进行解压,并在里面提取出String类型的xml文件。然后我需要对XML进行解析。我想我可以用XMLParser来解析。
问题:如何将压缩文件解压成字节格式?Data
类型,并从中获取xml文件作为 String
类型?
INPUT: String in Base64 format from GMail API fetch (A zip file attachment with only 1 xml file inside)
OUTPUT: String in XML format
PLATFORM: iOS 13/Swift 5.2/SwiftUI/Xcode 11.4
ACTION:
(INPUT)
base64: String | Decode -> Data
attachment.zip: Data | Decompress -> [Data]
ListOfFiles: [Data] | FirstIndex -> Data
dmarc.xml: Data | ContentOfXML -> String
(OUTPUT)
更新。 我试了一个叫 邮编 而它也失败了。
let path = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let url = path.appendingPathComponent(messageId+".zip")
do {
try data.write(to: url)
} catch {
print("Error while writing: "+error.localizedDescription)
}
do {
let unzipDirectory = try Zip.quickUnzipFile(url)
print(unzipDirectory)
} catch let error as NSError {
print("Error while unzipping: "+error.localizedDescription)
}
该代码导致以下错误
Error while unzipping: The operation couldn’t be completed. (Zip.ZipError error 1.)
我终于找到了。正如它提到的 参考文献1.邮件正文是用7位US-ASCII数据编码的。所以这也是为什么base64解码不成功的原因。
正如定义在 rfc1341:
编码类型为7BIT,要求正文已经是7位的邮件就绪表示。这是默认值 -- -- 即 "Content-Transfer-Encoding: 如果Content-Transfer-Encoding头域不存在,则假定为 "7BIT"。
在添加了以下内容后,整个代码就可以工作了。
let edata: String = result.data.replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/")
正如它在 参考文献2它只需要将'-'替换为'+',将'_'替换为'',就可以从gmail api接收到的base64数据。
func getAttachedData(messageId: String, attachmentId: String) {
decode(self.urlBase+messageId+"/attachments/"+attachmentId+"?"+self.urlKey) { (result: Attachment) in
let edata: String = result.data.replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/")
if let data = Data(base64Encoded: edata, options: .ignoreUnknownCharacters) {
let filemanager = FileManager.default
let path = try! filemanager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let url = path.appendingPathComponent(messageId+".zip")
do {
try data.write(to: url)
} catch {
print("Error while writing: "+error.localizedDescription)
}
do {
let unzipDirectory = try Zip.quickUnzipFile(url)
print("Unzipped")
do {
let filelist = try filemanager.contentsOfDirectory(at: unzipDirectory, includingPropertiesForKeys: [], options: [])
for filename in filelist {
print(filename.lastPathComponent)
print(filename.relativeString)
do {
let text = try String(contentsOf: filename, encoding: .utf8)
print(text)
DispatchQueue.main.async {
self.attachments.append(text)
}
} catch let error as NSError {
print("Error: \(error.localizedDescription)")
}
}
} catch let error {
print("Error: \(error.localizedDescription)")
}
} catch let error as NSError {
print("Error while unzipping: "+error.localizedDescription)
}
}
}
}