在Objective-C中使用AFNetworking上载可恢复的多部分文件

时间:2015-10-01 05:47:57

标签: ios file-upload afnetworking multipartform-data resume-upload

我想开发一个应用程序,我可能需要支持可恢复的文件上传。有没有办法支持可恢复文件上传。请注意,我也可以排队文件上传。

我正在使用AFNetworking。服务器:IIS。

如果可能,请提供强大的解决方案。我打开了(服务器 - 客户端)解决方案。

1 个答案:

答案 0 :(得分:1)

对于可恢复的上传,魔术必须在服务器端进行。我用于开发此上传的服务器使用的是tusd库https://github.com/tus/tusd

对不起,我可以在服务器端为您提供更多帮助。

在iOS上,您只需要实现三个HTTP请求

  1. 生成文件标识符的HTTP请求。您应该检索文件的标识符并将其与您的文件相关联(例如,在核心数据中)。

  2. HTTP GET请求传递文件的标识符以查找文件的偏移量(服务器上接收的文件的最后一个字节)。

  3. 上传文件的HTTP POST请求。如果要处理大文件,则必须使用NSInputStream才能分配内存。

      func uploadFileStream(file: MyFileClass, fileStream: NSInputStream){
    
        self.initialOffset = Double(file.offset)
        self.currentFile = file
        self.fileStream = fileStream 
    
        let url = NSURL(string: self.file.url)!
        var error: NSError?
    
        let request = NSMutableURLRequest(URL: url, cachePolicy: NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData, timeoutInterval: 10.0)
    
        request.HTTPMethod = "POST"
        request.addValue(file.identifier, forHTTPHeaderField: Constants.HEADER_FILE_IDENTIFIER)
        request.addValue(Constants.CONTENT_TYPE_DEFAULT,  forHTTPHeaderField: Constants.HEADER_FILE_CONTENT_TYPE)
    
        var task = session.uploadTaskWithStreamedRequest(request)
    
        fileStream.open()
    
        currentTask = task
        task.resume()
    }
    
  4. 你还必须实现NSURLSessionTaskDelegate来为streamRequest提供一个Body:

        func URLSession(session: NSURLSession, task: NSURLSessionTask, needNewBodyStream completionHandler: (NSInputStream!) -> Void) {
            if let stream = self.fileStream{
                // set the current offset as the starting point of the stream
                stream.setProperty(Int(self.currentFile.offset), forKey: NSStreamFileCurrentOffsetKey)
                // Set the stream as the request body
                completionHandler(stream)
            }
        }
    
            func URLSession(session: NSURLSession, task: NSURLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
    
                // Save current offset in database. This offset only indicates the amount of bytes sent, not the received in server.  
                let currentOffset = Double(self.initialOffset + Double(totalBytesSent))
                FilesDAO.saveOffset(fromFile: self.currentFile, offset: currentOffset)
    
        }
    
    func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?){
    
        if let err = error{
    
           // An error ocurred. You can retry the process of uploading
    
        }else{
    
           // The file was uploaded successfully
    
        }
    }
    

    基本上,您只需要在您的客户端上。然后,您将必须根据服务器实现设置不同的标头或请求正文