gpt4 book ai didi

ios - 后台使用单个 NSURLSession uploadTaskWithRequest 上传多张图片

转载 作者:IT王子 更新时间:2023-10-29 05:30:18 26 4
gpt4 key购买 nike

我想使用单个 uploadTaskWithRequest 方法在后台上传多张图片。在尝试以下代码时,后台 session 不支持从 NSData 返回上传任务...请问如何实现这一点

func createRequest (param : NSDictionary ,imagearray :NSMutableArray, strURL : String) -> NSURLRequest {

let boundary = generateBoundaryString()

let url = NSURL(string: strURL)
let request = NSMutableURLRequest(URL: url!)

request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.HTTPMethod = "POST"
request.HTTPBody = createBodyWithParameters(param, image_array:imagearray,boundary: boundary);

return request
}

func createBodyWithParameters(parameters: NSDictionary,image_array:NSMutableArray,boundary: String) -> NSData {
let body = NSMutableData()
for (key, value) in parameters {
if(value is String || value is NSString){
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(value)\r\n")
}
}
var i = 0;
for image in image_array {
let filename = "image\(i).jpg"
let data = UIImagePNGRepresentation(image as! UIImage);
let mimetype = "image/png"
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(self.filePathKey)\"; filename=\"\(filename)\"\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.appendData(data!)
body.appendString("\r\n")
i += 1;
}

body.appendString("--\(boundary)--\r\n")
// NSLog("data %@",NSString(data: body, encoding: NSUTF8StringEncoding)!);
return body
}

func postrequestwithformdata(requesturl:String,postparams:NSDictionary,postformadata:NSMutableArray,requestId:Int)
{

self.requestid = requestId;
let requestformdata = self.createRequest(postparams, imagearray: postformadata, strURL: requesturl);
let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(Contants.identifier)
let session: NSURLSession = NSURLSession(configuration:configuration, delegate: self, delegateQueue: NSOperationQueue.mainQueue());
let task: NSURLSessionUploadTask = session.uploadTaskWithRequest(requestformdata, fromData: requestformdata.HTTPBody!);
task.resume();

}

最佳答案

要在后台 session 中上传,必须先将数据保存到文件中。

  1. 使用 writeToFile:options: 将数据保存到文件中.
  2. 调用NSURLSession uploadTaskWithRequest:fromFile:创建任务。注意请求中不能包含HTTPBody中的数据,否则会上传失败。
  3. 处理 URLSession:didCompleteWithError: 中的完成委托(delegate)方法。

您可能还想处理在应用程序处于后台时完成的上传。

  1. 实现 application:handleEventsForBackgroundURLSession:completionHandler在 AppDelegate 中。
  2. 使用提供的标识符创建一个 NSURLSession。
  3. 按照常规上传响应委托(delegate)方法(例如处理 URLSession:didCompleteWithError: 中的响应)
  4. 调用URLSessionDidFinishEventsForBackgroundURLSession当您完成对事件的处理时。

为了使其更易于管理,为每个上传任务创建一个 NSURLSession,每个任务都有一个唯一标识符。

引用URL Session Programming Guide了解实现细节。

示例 AppDelegate:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, NSURLSessionDelegate, NSURLSessionTaskDelegate {

var window: UIWindow?

typealias CompletionHandler = () -> Void

var completionHandlers = [String: CompletionHandler]()

var sessions = [String: NSURLSession]()


func upload(request: NSURLRequest, data: NSData)
{
// Create a unique identifier for the session.
let sessionIdentifier = NSUUID().UUIDString

let directoryURL = NSFileManager.defaultManager().URLsForDirectory(.CachesDirectory, inDomains: .UserDomainMask).first!
let fileURL = directoryURL.URLByAppendingPathComponent(sessionIdentifier)

// Write data to cache file.
data.writeToURL(fileURL, atomically: true);

let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(sessionIdentifier)

let session: NSURLSession = NSURLSession(
configuration:configuration,
delegate: self,
delegateQueue: NSOperationQueue.mainQueue()
)

// Store the session, so that we don't recreate it if app resumes from suspend.
sessions[sessionIdentifier] = session

let task = session.uploadTaskWithRequest(request, fromFile: fileURL)

task.resume()
}

// Called when the app becomes active, if an upload completed while the app was in the background.
func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: CompletionHandler) {

let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(identifier)

if sessions[identifier] == nil {

let session = NSURLSession(
configuration: configuration,
delegate: self,
delegateQueue: NSOperationQueue.mainQueue()
)

sessions[identifier] = session
}

completionHandlers[identifier] = completionHandler
}

func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {

// Handle background session completion handlers.
if let identifier = session.configuration.identifier {

if let completionHandler = completionHandlers[identifier] {
completionHandler()
completionHandlers.removeValueForKey(identifier)
}

// Remove session
sessions.removeValueForKey(identifier)
}

// Upload completed.
}
}

要在单个请求中上传多张图片,必须先将图片编码为 multipart/formdata MIME 类型,就像您所做的那样。不同之处在于,整个 MIME 消息必须保存到单个文件,即上传到服务器的文件。

下面是一个示例,说明如何执行此操作。它通过将 MIME 部分直接序列化到文件来工作。您也可以在 NSData 中构建消息,尽管在处理大文件时可能会遇到内存限制。

func uploadImages(request: NSURLRequest, images: [UIImage]) {

let uuid = NSUUID().UUIDString
let boundary = String(count: 24, repeatedValue: "-" as Character) + uuid

// Open the file
let directoryURL = NSFileManager.defaultManager().URLsForDirectory(.CachesDirectory, inDomains: .UserDomainMask).first!

let fileURL = directoryURL.URLByAppendingPathComponent(uuid)
let filePath = fileURL.path!

NSFileManager.defaultManager().createFileAtPath(filePath, contents: nil, attributes: nil)

let file = NSFileHandle(forWritingAtPath: filePath)!


// Write each image to a MIME part.
let newline = "\r\n"

for (i, image) in images.enumerate() {

let partName = "image-\(i)"
let partFilename = "\(partName).png"
let partMimeType = "image/png"
let partData = UIImagePNGRepresentation(image)

// Write boundary header
var header = ""
header += "--\(boundary)" + newline
header += "Content-Disposition: form-data; name=\"\(partName)\"; filename=\"\(partFilename)\"" + newline
header += "Content-Type: \(partMimeType)" + newline
header += newline

let headerData = header.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)

print("")
print("Writing header #\(i)")
print(header)

print("Writing data")
print("\(partData!.length) Bytes")

// Write data
file.writeData(headerData!)
file.writeData(partData!)
}

// Write boundary footer
var footer = ""
footer += newline
footer += "--\(boundary)--" + newline
footer += newline

print("")
print("Writing footer")
print(footer)

let footerData = footer.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
file.writeData(footerData!)

file.closeFile()

// Add the content type for the request to multipart.
let outputRequest = request.copy() as! NSMutableURLRequest

let contentType = "multipart/form-data; boundary=\(boundary)"
outputRequest.setValue(contentType, forHTTPHeaderField: "Content-Type")


// Start uploading files.
upload(outputRequest, fileURL: fileURL)
}

关于ios - 后台使用单个 NSURLSession uploadTaskWithRequest 上传多张图片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38349943/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com