14

I am using NSURLSessionUploadTask to upload a file.

Here are some parts of my code not complete

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

let sessionTask:NSURLSessionUploadTask = session.uploadTaskWithStreamedRequest(request

But the problem is I am unable to get the JSON response the server sends back.

The following delegate also not firing but other delegates are firing

func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData)

Code that I am using:

func sendFileToServer1(fileName:String,fileData:NSData,serverURL:String){

let body = NSMutableData()

let mimetype = "application/octet-stream"
//        let mimetype = "video/quicktime"

let boundary = "Boundary-\(NSUUID().UUIDString)"
let url = NSURL(string: serverURL)

let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
request.setValue("multipart/form-data; boundary=----\(boundary)", forHTTPHeaderField: "Content-Type")
body.appendData("------\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Disposition:form-data; name=\"file\"; filename=\"\(fileName)\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Type: \(mimetype)\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData(fileData)
body.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("------\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Disposition:form-data; name=\"submit\"\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Submit\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("------\(boundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
request.HTTPBody=body

let config:NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
let session:NSURLSession = NSURLSession(configuration: config, delegate: self, delegateQueue: NSOperationQueue .mainQueue())
let sessionTask:NSURLSessionUploadTask = session.uploadTaskWithStreamedRequest(request)
sessionTask.resume()
}

func URLSession(session: NSURLSession, didBecomeInvalidWithError error: NSError?) {
    print("error")
 }

func URLSession(session: NSURLSession, task: NSURLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
    print("Bytes sent:\(bytesSent) Total bytes sent:\(totalBytesSent) Total bytes expected to send:\(totalBytesExpectedToSend)")
}

func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {
    print("response:\(response as! NSHTTPURLResponse)")
}

func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
    print("data didReceiveData")
}

I have conformed to the delegates

  1. NSURLSessionDataDelegate
  2. NSURLSessionDelegate
  3. NSURLSessionTaskDelegate

Thanks

RajuBhai Rocker
  • 723
  • 1
  • 7
  • 24
  • Refer this: https://www.raywenderlich.com/110458/nsurlsession-tutorial-getting-started – Santosh Aug 08 '16 at 14:35
  • As far as I am aware , In upload task there is no way to read the server respsone data....we can get server response header fields but not payload data that server sends.Correct me if I am wrong – RajuBhai Rocker Aug 08 '16 at 14:37
  • 1
    What other delegate are fired? – Larme Aug 09 '16 at 07:54
  • func URLSession(session: NSURLSession, task: NSURLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) { – RajuBhai Rocker Aug 09 '16 at 08:01
  • Implement all delegate methods and tell us each that is called – Wain Aug 11 '16 at 06:55
  • 1
    share some more code – SHN Aug 11 '16 at 09:15
  • I have updated my question with code – RajuBhai Rocker Aug 11 '16 at 10:03
  • Try also implementing connection:needNewBodyStream:. It should create and return a new NSStream object in the same way you created the initial request. As per Apple doc for uploadTaskWithStreamedRequest: : "The body stream and body data in this request object are ignored, and NSURLSession calls its delegate’s URLSession:task:needNewBodyStream: method to provide the body data." – SHN Aug 11 '16 at 11:19
  • @SHN - Its not getting called I tried it. – RajuBhai Rocker Aug 11 '16 at 17:11
  • @RajuBhaiRocker you need to use `NSURLSessionDataTask` as you are Posting data to server using API, you are not uploading/transfering any resource to storage. Lets say if you upload a video to amazon bucket at that time you can use `NSURLSessionUploadTask` which is meant for Uploading. Here you are Posting Image, video etc in API request. – Dipen Panchasara Aug 16 '16 at 12:22

2 Answers2

1

You shouldn't be using uploadTaskWithStreamedRequest: if you're creating the data when you create the request. That's intended for uploading huge chunks of data where you need to read the data from a file and encode it a bit at a time, sending it out a bit at a time. (And as mentioned, you have to provide the needNewBodyStream method if you do that.)

Chances are, you should be using uploadTaskWithRequest:fromData: and providing the body data blob as the fromData parameter.

You also don't need to set the body data in the request. NSURLSession ignores that as a rule.

You might also consider uploadTaskWithRequest:fromData:completionHandler:, which will let you specify a block to run with the entire data when the upload is finished, saving you from having to provide a delegate method to accumulate the data.

dgatwood
  • 10,129
  • 1
  • 28
  • 49
  • So in that case , Can I get the percentage of upload as well the response payload data ? – RajuBhai Rocker Aug 16 '16 at 11:33
  • 1
    I *think* the delegate methods for upload still fire when you use a completion handler. But even if they don't, **NSURLSession** tasks fully support key-value observing, so you can always observe changes to the `countOfBytesSent` and `countOfBytesExpectedToSend` properties on the task and recompute the upload percentage whenever either of those values changes. – dgatwood Aug 18 '16 at 20:16
0

As NSURLSessionUploadTask is a subclass of NSURLSessionDataTask, you could try using methods from NSURLSessionDataDelegate:

func urlSession(_ session: NSURLSession, dataTask: NSURLSessionDataTask, didReceive response: NSURLResponse, completionHandler: (NSURLSession.ResponseDisposition) -> Void)

According to the documentation:

Tells the delegate that the data task received the initial reply (headers) from the server.

yageek
  • 4,115
  • 3
  • 30
  • 48