我正在尝试上传图像和文本文件(将其作为数据上传)。
到目前为止,我可以正确地单独上传图像,也可以单独上传文本文件数据,将其作为.txt成功上传。
现在我需要同时上传图像和 .txt 文件...
我不知道如何在我的 IOS 应用程序中为此设置参数....
到目前为止,这就是我上传 .txt 文件的方式(基本上与我上传图像的方式相同,但我更改了“文件名”和“mimetype”)
func createBodyWithParameters(parameters: [String : Any]?, filePathKey: String?,filePathKey1: String?, imageDataKey: NSData,imageDataKey1: NSData, boundary: String) -> NSData {
let body = NSMutableData();
if parameters != nil {
for (key, value) in parameters! {
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(value)\r\n")
}
}
let filename = "post-\(uuid).txt"
let mimetype = "image/txt"
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.append(imageDataKey as Data)
body.appendString("\r\n")
body.appendString("--\(boundary)--\r\n")
return body
}
现在我不确定如何使用该参数保存图像和 .txt 文件。
然而,这是我上传它的其余 swift 代码:
let param = [
"id" : id,
"uuid" : uuid,
"Text" : Text,
"Title" : Title
] as [String : Any]
let boundary = "Boundary-\(NSUUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let data: Data = NSKeyedArchiver.archivedData(withRootObject: blogattributedText)
var imageData = NSData()
let image = CoverImage
let width = CGSize(width: self.view.frame.width, height: image.size.height * (self.view.frame.width / image.size.width))
imageData = UIImageJPEGRepresentation(imageWithImage(image, scaledToSize: width), 0.5)! as NSData
// ... body
request.httpBody = createBodyWithParameters(parameters: param, filePathKey: "file",filePathKey1: "file1", imageDataKey: data as NSData,imageDataKey1: imageData as NSData, boundary: boundary) as Data
如果有人需要查看我的代码或不理解我的问题,请告诉我!
在此先感谢任何可以提供帮助的人!!
最佳答案
如果您不想迷失在创建复杂请求的杂草中,像 Alamofire 这样的第三方库会很聪明。它与 AFNetworking 的作者相同,但它是一个原生的 Swift 库。
所以,一个 Alamofire 实现可能看起来像:
func performRequest(urlString: String, id: String, uuid: String, text: String, title: String, blogAttributedText: NSAttributedString, image: UIImage) {
let parameters = [
"id" : id,
"uuid" : uuid,
"Text" : text,
"Title" : title
]
let imageData = UIImageJPEGRepresentation(image, 0.5)!
let blogData = NSKeyedArchiver.archivedData(withRootObject: blogAttributedText)
Alamofire.upload(
multipartFormData: { multipartFormData in
for (key, value) in parameters {
if let data = value.data(using: .utf8) {
multipartFormData.append(data, withName: key)
}
}
multipartFormData.append(imageData, withName: "image", fileName: "image.jpg", mimeType: "image/jpeg")
multipartFormData.append(blogData, withName: "blog", fileName: "blog.archive", mimeType: "application/octet-stream")
},
to: urlString,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload
.validate()
.responseJSON { response in
switch response.result {
case .success(let value):
print("responseObject: \(value)")
case .failure(let responseError):
print("responseError: \(responseError)")
}
}
case .failure(let encodingError):
print("encodingError: \(encodingError)")
}
})
}
如果您要自己构建此请求,我建议您做一些事情。首先,由于您要发送不同类型的文件,您可能需要一些不错的类型来封装它:
struct FilePayload {
let fieldname: String
let filename: String
let mimetype: String
let payload: Data
}
我也不确定如何制作
image/txt
mime 类型。我可能会使用 application/octet-stream
作为存档。无论如何,请求的构建可能如下:
/// Create request.
///
/// - Parameters:
/// - url: The URL to where the post will be sent.
/// - id: The identifier of the entry
/// - uuid: The UUID of the entry
/// - text: The text.
/// - title: The title.
/// - blogAttributedText: The attributed text of the blog entry.
/// - image: The `UIImage` of the image to be included.
///
/// - Returns: The `URLRequest` that was created
func createRequest(url: URL, id: String, uuid: String, text: String, title: String, blogAttributedText: NSAttributedString, image: UIImage) -> URLRequest {
let parameters = [
"id" : id,
"uuid" : uuid,
"Text" : text, // I find it curious to see uppercase field names (I'd use lowercase for consistency's sake, but use whatever your PHP is looking for)
"Title" : title
]
let boundary = "Boundary-\(NSUUID().uuidString)"
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept") // adjust if your response is not JSON
// use whatever field name your PHP is looking for the image; I used `image`
let imageData = UIImageJPEGRepresentation(image, 0.5)!
let imagePayload = FilePayload(fieldname: "image", filename: "image.jpg", mimetype: "image/jpeg", payload: imageData)
// again, use whatever field name your PHP is looking for the image; I used `blog`
let blogData = NSKeyedArchiver.archivedData(withRootObject: blogAttributedText)
let blogPayload = FilePayload(fieldname: "blog", filename: "blog.archive", mimetype: "application/octet-stream", payload: blogData)
request.httpBody = createBody(with: parameters, files: [imagePayload, blogPayload], boundary: boundary)
return request
}
/// Create body of the multipart/form-data request.
///
/// - Parameters:
/// - parameters: The optional dictionary containing keys and values to be passed to web service.
/// - files: The list of files to be included in the request.
/// - boundary: The `multipart/form-data` boundary
///
/// - Returns: The `Data` of the body of the request.
private func createBody(with parameters: [String: String]?, files: [FilePayload], boundary: String) -> Data {
var body = Data()
if parameters != nil {
for (key, value) in parameters! {
body.append("--\(boundary)\r\n")
body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.append("\(value)\r\n")
}
}
for file in files {
body.append("--\(boundary)\r\n")
body.append("Content-Disposition: form-data; name=\"\(file.fieldname)\"; filename=\"\(file.filename)\"\r\n")
body.append("Content-Type: \(file.mimetype)\r\n\r\n")
body.append(file.payload)
body.append("\r\n")
}
body.append("--\(boundary)--\r\n")
return body
}
/// Create boundary string for multipart/form-data request
///
/// - returns: The boundary string that consists of "Boundary-" followed by a UUID string.
private func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().uuidString)"
}
在哪里
extension Data {
/// Append string to Data
///
/// Rather than littering my code with calls to `dataUsingEncoding` to convert strings to `Data`, and then add that data to the `Data`, this wraps it in a nice convenient little `Data` extension. This converts using UTF-8.
///
/// - parameter string: The string to be added to the mutable `Data`.
mutating func append(_ string: String) {
if let data = string.data(using: .utf8) {
append(data)
}
}
}
显然这是 Swift 3 代码,所以我删除了
NSMutableData
引用。关于ios - MYSQL 和 Swift - 上传图片和文件 ||使用 Alamofire 会更好吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40527140/