Swift: 文件在 base64 编码后似乎已损坏

Swift: Files appear to be corrupt after base64 encoding

我正在尝试将文件作为附件上传到我的 Frappe 实例,运行 遇到了几个问题。 其中第一个是相关的,并且记录了一个填充错误:in this question。我把它放在这里只是为了以防它在某种程度上是我犯的错误的一部分。

我的第二个问题,也是这个问题的重点是,当我上传附件时,它们似乎已损坏。一个小 xml 文件可以打开,但大部分是乱码。更大的 PDF 文件甚至无法打开。我的假设是我在使用 base64 编码时犯了一些初学者错误。

从本地获取数据URL:

let settingsLocation = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("SettingsList.plist")
let fileData = try Data.init(contentsOf: settingsLocation)

然后将其传递给以下函数:

    public func attachFileToCloudResource(resourceType: String, resourceName: String, attachment: Data) {
    
    let fileAsString = (attachment.base64EncodedString().replacingOccurrences(of: "+", with: "%2B") + "==")
    
    var request = URLRequest(url: URL(string: FRAPPE_INSTANCE + FRAPPE_METHODS + FRAPPE_UPLOAD_ATTACHMENT)!)

    var components = URLComponents(url: request.url!, resolvingAgainstBaseURL: false)!

    components.queryItems = [
        URLQueryItem(name: FRAPPE_DOCTYPE, value: resourceType),
        URLQueryItem(name: FRAPPE_DOCNAME, value: resourceName),
        URLQueryItem(name: FRAPPE_FILENAME, value: "testFile.xml"),
        URLQueryItem(name: FRAPPE_DATA, value: fileAsString),
        URLQueryItem(name: FRAPPE_PRIVATE, value: "1"),
        URLQueryItem(name: FRAPPE_DECODE_BASE64, value: "1")
    ]

    let query = components.url!.query

    request.httpMethod = "POST"
    request.addValue("token \(API_KEY):\(API_SECRET)", forHTTPHeaderField: "Authorization")
    request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    request.httpBody = Data(query!.utf8)


    // url session and dataTask send data to server below this point
    }

这工作正常,因为我从服务器得到了肯定的响应并且文件附加到指定的记录 - 但是当文件被下载(通过网络浏览器)时,无论文件类型如何,它似乎已损坏我试试。

如有任何帮助,我们将不胜感激。

我找到了适合我的解决方案。

首先,我使用在线 base64 编码器对一个简单的 xml 文件进行编码。 然后我使用生成的 base64 字符串重新创建我的 POST 使用 Postman (很棒的工具,只是刚刚发现它)。

这有效,我的文件已附加到指定记录且未损坏。

然后我使用 Postman 的功能生成代码,看看它认为我用于文件数据的 base64String 应该是什么样子。我发现所有的 '+' 字符都被替换为 "%2B"。

进一步调查发现 Swift 中的查询项进行了一些它自己的百分比编码,但是 给出了为什么“+”字符有效而不是百分比编码的解释默认情况下。

最终结果是我从原始 base64String 中删除了手动百分比编码:

let fileAsString = attachment.base64EncodedString() + "=="

我在从查询项生成 httpBody 时添加了它:

request.httpBody = Data(query!.replacingOccurrences(of: "+", with: "%2B").utf8)