将 .MOV 视频文件作为 POST 请求的一部分发送到自己的服务器作为 Swift 中 multipart/form-data 请求的一部分不起作用
Sending .MOV video file as part of POST request to own server as part of a multipart/form-data request in Swift not working
我们正在尝试使用 Swift 和 multipart/form-data post 请求将视频从 iOS 设备或 iOS 模拟器发送到我们自己托管在 AWS 上的服务器.
我们在 postman 中正确设置了请求,并测试了它是否成功。我们在 post 人工响应日志中收到成功的 200 个 HTTP 状态代码,并且视频数据正在正确传输,因为我们能够在设备上播放视频以及在 AWS 上的 S3 中观看时。
但是,在 Swift 中生成 multipart/form-data 请求时,我们到目前为止还没有成功。我们最初根据以下代码片段使用 Postman 生成的代码:
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
var semaphore = DispatchSemaphore (value: 0)
let parameters = [
[
"key": "video",
"src": "device_file_url",
"type": "file"
]] as [[String : Any]]
let boundary = "Boundary-\(UUID().uuidString)"
var body = ""
var error: Error? = nil
for param in parameters {
if param["disabled"] == nil {
let paramName = param["key"]!
body += "--\(boundary)\r\n"
body += "Content-Disposition:form-data; name=\"\(paramName)\""
if param["contentType"] != nil {
body += "\r\nContent-Type: \(param["contentType"] as! String)"
}
let paramType = param["type"] as! String
if paramType == "text" {
let paramValue = param["value"] as! String
body += "\r\n\r\n\(paramValue)\r\n"
} else {
let paramSrc = param["src"] as! String
let fileData = try NSData(contentsOfFile:paramSrc, options:[]) as Data
let fileContent = String(data: fileData, encoding: .utf8)!
body += "; filename=\"\(paramSrc)\"\r\n"
+ "Content-Type: \"content-type header\"\r\n\r\n\(fileContent)\r\n"
}
}
}
body += "--\(boundary)--\r\n";
let postData = body.data(using: .utf8)
var request = URLRequest(url: URL(string: "https://url_to_server/")!,timeoutInterval: Double.infinity)
request.addValue("token xxxx", forHTTPHeaderField: "Authorization")
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print(String(describing: error))
semaphore.signal()
return
}
print(String(data: data, encoding: .utf8)!)
semaphore.signal()
}
task.resume()
semaphore.wait()
这一行似乎将文件转换为字节数组根据这张图片Video data in Bytes :
let fileData = try NSData(contentsOfFile:paramSrc, options:[]) as Data
然后以下行出错(b/c 由于从上面的行中命中 nil 值而导致解包失败):
let fileContent = String(data: fileData, encoding: .utf8)!
因此我们假设问题可能是由于 .MOV/video 文件在传递到请求正文之前转换为数据对象/字符串造成的。
然后我们对 fileContent 行使用了另一种解码策略,如下所示:
let fileContent = String(decoding: fileData, as: UTF8.self)
就收到成功的 HTTP 响应代码 200 和服务器端的 videoUrl 识别已发送对象而言,这是成功的。然而,当打印 fileContent 字符串时,它是一长串随机字符,如下图所示:
Swift console log of fileContent string
并且在 AWS S3 中查看端点时,资产显示没有支持格式的视频并且找到 mime 类型(所有浏览器都有相同的响应)Error of video format screenshot 表明视频到数据的转换是 incorrect/corrupted 因此无法正常工作。
我的问题是:
- 从 iOS 设备或模拟器将视频数据作为 HTTP 请求的一部分发送到服务器的最有效方法是什么? Multipart/form-data?
--- 1.2) 如果 Multipart/form-data 是最好的方法,那么将视频转换为数据并作为 post 请求的一部分发送的正确方法是什么?
- 有没有其他方法有利于发送此类数据?
考虑到大量应用程序将视频从设备发送到服务器,我希望有关于此类主题的大量文档,但我还没有找到一个有效的解决方案。
如有任何帮助,我们将不胜感激!
简介:
我不会将它转换成字符串...
认为每个数据都可以是有效的 UTF8 字符串,这是一个很大的错误......但是一个有效的 UTF8 字符串到 Data
,每次都有效。
let stringImage = String(data: anyUIImage.pngData()!, encoding: .utf8)
正常应该给nil
值...
正在使用:
相反,使 body
成为 Data
,而不是 String
,因为最终 httpBody
是 Data
。
var body = Data()
当你想追加一个String
:
body += "--\(boundary)\r\n"
=>
body += Data("--\(boundary)\r\n".utf8)
如果您有 Data
参数,请直接附加它。
然后,为您的视频内容;
let paramSrc = param["src"] as! String
let fileData = try NSData(contentsOfFile:paramSrc, options:[]) as Data
let fileContent = String(data: fileData, encoding: .utf8)!
body += "; filename=\"\(paramSrc)\"\r\n"
+ "Content-Type: \"content-type header\"\r\n\r\n\(fileContent)\r\n"
应该是:
if let source = param["src"] as? String, let fileContent = try? Data(contentsOf: source) {
body += Data("; filename=\"\(paramSrc)\"\r\n".utf8)
body += Data("Content-Type: \"content-type header\"\r\n".utf8)
//Now, appending the data
body += Data("\r\n".utf8)
body += fileContent
body += Data("\r\n".utf8)
}
最后:
request.httpBody = body
我们正在尝试使用 Swift 和 multipart/form-data post 请求将视频从 iOS 设备或 iOS 模拟器发送到我们自己托管在 AWS 上的服务器.
我们在 postman 中正确设置了请求,并测试了它是否成功。我们在 post 人工响应日志中收到成功的 200 个 HTTP 状态代码,并且视频数据正在正确传输,因为我们能够在设备上播放视频以及在 AWS 上的 S3 中观看时。
但是,在 Swift 中生成 multipart/form-data 请求时,我们到目前为止还没有成功。我们最初根据以下代码片段使用 Postman 生成的代码:
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
var semaphore = DispatchSemaphore (value: 0)
let parameters = [
[
"key": "video",
"src": "device_file_url",
"type": "file"
]] as [[String : Any]]
let boundary = "Boundary-\(UUID().uuidString)"
var body = ""
var error: Error? = nil
for param in parameters {
if param["disabled"] == nil {
let paramName = param["key"]!
body += "--\(boundary)\r\n"
body += "Content-Disposition:form-data; name=\"\(paramName)\""
if param["contentType"] != nil {
body += "\r\nContent-Type: \(param["contentType"] as! String)"
}
let paramType = param["type"] as! String
if paramType == "text" {
let paramValue = param["value"] as! String
body += "\r\n\r\n\(paramValue)\r\n"
} else {
let paramSrc = param["src"] as! String
let fileData = try NSData(contentsOfFile:paramSrc, options:[]) as Data
let fileContent = String(data: fileData, encoding: .utf8)!
body += "; filename=\"\(paramSrc)\"\r\n"
+ "Content-Type: \"content-type header\"\r\n\r\n\(fileContent)\r\n"
}
}
}
body += "--\(boundary)--\r\n";
let postData = body.data(using: .utf8)
var request = URLRequest(url: URL(string: "https://url_to_server/")!,timeoutInterval: Double.infinity)
request.addValue("token xxxx", forHTTPHeaderField: "Authorization")
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print(String(describing: error))
semaphore.signal()
return
}
print(String(data: data, encoding: .utf8)!)
semaphore.signal()
}
task.resume()
semaphore.wait()
这一行似乎将文件转换为字节数组根据这张图片Video data in Bytes :
let fileData = try NSData(contentsOfFile:paramSrc, options:[]) as Data
然后以下行出错(b/c 由于从上面的行中命中 nil 值而导致解包失败):
let fileContent = String(data: fileData, encoding: .utf8)!
因此我们假设问题可能是由于 .MOV/video 文件在传递到请求正文之前转换为数据对象/字符串造成的。
然后我们对 fileContent 行使用了另一种解码策略,如下所示:
let fileContent = String(decoding: fileData, as: UTF8.self)
就收到成功的 HTTP 响应代码 200 和服务器端的 videoUrl 识别已发送对象而言,这是成功的。然而,当打印 fileContent 字符串时,它是一长串随机字符,如下图所示: Swift console log of fileContent string
并且在 AWS S3 中查看端点时,资产显示没有支持格式的视频并且找到 mime 类型(所有浏览器都有相同的响应)Error of video format screenshot 表明视频到数据的转换是 incorrect/corrupted 因此无法正常工作。
我的问题是:
- 从 iOS 设备或模拟器将视频数据作为 HTTP 请求的一部分发送到服务器的最有效方法是什么? Multipart/form-data? --- 1.2) 如果 Multipart/form-data 是最好的方法,那么将视频转换为数据并作为 post 请求的一部分发送的正确方法是什么?
- 有没有其他方法有利于发送此类数据?
考虑到大量应用程序将视频从设备发送到服务器,我希望有关于此类主题的大量文档,但我还没有找到一个有效的解决方案。
如有任何帮助,我们将不胜感激!
简介:
我不会将它转换成字符串...
认为每个数据都可以是有效的 UTF8 字符串,这是一个很大的错误......但是一个有效的 UTF8 字符串到 Data
,每次都有效。
let stringImage = String(data: anyUIImage.pngData()!, encoding: .utf8)
正常应该给nil
值...
正在使用:
相反,使 body
成为 Data
,而不是 String
,因为最终 httpBody
是 Data
。
var body = Data()
当你想追加一个String
:
body += "--\(boundary)\r\n"
=>
body += Data("--\(boundary)\r\n".utf8)
如果您有 Data
参数,请直接附加它。
然后,为您的视频内容;
let paramSrc = param["src"] as! String
let fileData = try NSData(contentsOfFile:paramSrc, options:[]) as Data
let fileContent = String(data: fileData, encoding: .utf8)!
body += "; filename=\"\(paramSrc)\"\r\n"
+ "Content-Type: \"content-type header\"\r\n\r\n\(fileContent)\r\n"
应该是:
if let source = param["src"] as? String, let fileContent = try? Data(contentsOf: source) {
body += Data("; filename=\"\(paramSrc)\"\r\n".utf8)
body += Data("Content-Type: \"content-type header\"\r\n".utf8)
//Now, appending the data
body += Data("\r\n".utf8)
body += fileContent
body += Data("\r\n".utf8)
}
最后:
request.httpBody = body