cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Announcements
Want to learn some quick and useful tips to make your day easier? Check out how Calvin uses Replay to get feedback from other teams at Dropbox here.

Dropbox API Support & Feedback

Find help with the Dropbox API from other developers.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Re: parsing upload session finish error

parsing upload session finish error

Christian T.16
New member | Level 1

Can you provide an example of how to parse an upload session finish error. Here's what I have but none of these cases are triggered. I do get Error but no further details. Thanks.

                        // we're ready to finish the upload and commit the file

                        client.files.uploadSessionFinish(cursor: Files.UploadSessionCursor(sessionId: result.sessionId, offset: position),

                            commit: Files.CommitInfo(path: “somePath”),

                            body:data).response { response, error in

                                

                                if let result = response {

                                    print("UPLOAD SESSION FINISH RESULT: \(result)")

                                } else {

                                    print("UPLOAD SESSION FINISH ERROR: \(error!)!")

                                    switch error {

                                        case .LookupFailed:

                                            print("LOOKUP FAILED")

                                        case .Path:

                                            print("PATH ERROR")

                                        case .Other:

                                            print("OTHER ERROR")

                                    }

                                }

 

                        }

 

17 Replies 17

Greg-DB
Dropbox Staff

Yes, offset is the total amount of data uploaded so for a single file upload session, not including the data you're about to upload in the current call. You can think of it as the start index of the data you're sending in that call. For the first call, it's 0.

Christian T.16
New member | Level 1

Can I only call another append when the previous append has returned? Currently, I'm calling all of them in a while loop and not waiting on a return.

Christian T.16
New member | Level 1

Here's my latest code. It seems like the append operations aren't being processed in the order they are called, so I'll get incorrect offset errors. For example, I had seven append calls, two succeeded, five failed.

let chunkLength:UInt64 = 1024 * 1024 * 5 //in MB
let fileLength:UInt64 = UInt64(data.length)//Double(data.length)/1024/1024 //in MB

print("FILE LENGTH: \(fileLength)")
print("CHUNK LENGTH: \(chunkLength)")

if (fileLength < chunkLength) {
print("LESS THAN CHUNK SIZE")
//Upload File
if let client = Dropbox.authorizedClient {
client.files.upload(path:destinationPath+uploadFilename!, body:data).response { response, error in
if let metadata = response {
completion()
} else {
print("UPLOAD ERROR(DropboxUploader.swift): \(error!)")
}
}
}

} else {

print("MORE THAN CHUNK SIZE")

var startPosition:UInt64 = 0
var loopCounter:UInt64 = 0
var tempData:NSData = data
var range:NSRange = NSMakeRange(Int(startPosition), Int(chunkLength))

//Upload File
if let client = Dropbox.authorizedClient {

client.files.uploadSessionStart(body: NSData()).response { response, error in

if let result = response {

print("UPLOAD SESSION START RESULT: \(result)")

while (startPosition <= fileLength) {

startPosition = chunkLength*loopCounter
print("LOOP COUNTER: \(loopCounter)")
print("START POSITION: \(startPosition)")

if (startPosition+chunkLength >= UInt64(data.length)) {

print("FINAL START POSITION: \(startPosition)")

range = NSMakeRange(Int(startPosition), (data.length)-Int(startPosition))
print("FINAL RANGE: \(range)\n")
tempData = data.subdataWithRange(range)

client.files.uploadSessionAppend(sessionId: result.sessionId, offset: startPosition, body: tempData).response { response, error in

if let result = response {
print("FINAL APPEND RESULT: \(result)")
} else if let callError = error {
print("FINAL APPEND ERROR: \(error)")
}
}

break
}

range = NSMakeRange(Int(startPosition), Int(chunkLength))
print("RANGE: \(range)\n")
tempData = data.subdataWithRange(range)

client.files.uploadSessionAppend(sessionId: result.sessionId, offset: startPosition, body: tempData).response { response, error in

if let result = response {
print("APPEND RESULT: \(result)")
} else if let callError = error {
print("APPEND ERROR: \(error)")
}
}

loopCounter++

}

// we're ready to finish the upload and commit the file
client.files.uploadSessionFinish(cursor: Files.UploadSessionCursor(sessionId: result.sessionId, offset: startPosition),
commit: Files.CommitInfo(path: destinationPath+uploadFilename!),
// no additional data to add at this point in this case
body:NSData()).response { response, error in

if let result = response {
print("Result: \(result)")
} else if let callError = error {
switch callError as CallError {
case .RouteError(let boxed, let requestId):
print("RouteError[\(requestId)]:")
switch boxed.unboxed as Files.UploadSessionFinishError {
case .Path(let fileLookupError):
print("Path: ")
switch fileLookupError {
case .MalformedPath(let malformedPathError):
print("MalformedPath: \(malformedPathError)")
case .Conflict(let writeConflictError):
print("Conflict:")
switch writeConflictError {
case .File:
print("File")
case .FileAncestor:
print("FileAncestor")
case .Folder:
print("Folder")
case .Other:
print("Other")
}
case .DisallowedName:
print("DisallowedName")
case .InsufficientSpace:
print("InsufficientSpace")
case .NoWritePermission:
print("NoWritePermission")
case .Other:
print("Other")
}
case .LookupFailed(let uploadSessionLookupError):
print("LookupFailed:")
switch uploadSessionLookupError {
case .Closed:
print("Closed")
case .IncorrectOffset(let uploadSessionOffsetError):
print("IncorrectOffset: \(uploadSessionOffsetError)")
case .NotFound:
print("NotFound")
case .Other:
print("Other")
}
case .Other:
print("Other")
}
case .BadInputError(let message, let requestId):
print("BadInputError[\(requestId)]: \(message)")
case .HTTPError(let code, let message, let requestId):
print("HTTPError[\(requestId)]: \(code): \(message)")
case .InternalServerError(let code, let message, let requestId):
print("InternalServerError[\(requestId)]: \(code): \(message)")
case .OSError(let err):
print("OSError: \(err)")
case .RateLimitError:
print("RateLimitError")
}
}

}

} else {
print("UPLOAD SESSION START ERROR(DropboxUploader.swift): \(error!)")
}
}
}
}

 

Here's the console output....

FILE LENGTH: 33700300
CHUNK LENGTH: 5242880
MORE THAN CHUNK SIZE
UPLOAD SESSION START RESULT: {
"session_id" = "AAAAAAAAATQlmkMM-eETZA";
}
LOOP COUNTER: 0
START POSITION: 0
RANGE: (0,5242880)

LOOP COUNTER: 1
START POSITION: 5242880
RANGE: (5242880,5242880)

LOOP COUNTER: 2
START POSITION: 10485760
RANGE: (10485760,5242880)

LOOP COUNTER: 3
START POSITION: 15728640
RANGE: (15728640,5242880)

LOOP COUNTER: 4
START POSITION: 20971520
RANGE: (20971520,5242880)

LOOP COUNTER: 5
START POSITION: 26214400
RANGE: (26214400,5242880)

LOOP COUNTER: 6
START POSITION: 31457280
FINAL START POSITION: 31457280
FINAL RANGE: (31457280,2243020)

APPEND RESULT: ()
APPEND ERROR: Optional([request-id fb45a248b79b4989ff52163d957850d1] API route error - {
".tag" = "incorrect_offset";
"correct_offset" = 5242880;
})
APPEND ERROR: Optional([request-id 75490d1c812ef1072aef17269dda576d] API route error - {
".tag" = "incorrect_offset";
"correct_offset" = 5242880;
})
APPEND RESULT: ()
RouteError[Optional("054b4b3848a92df65a9f0cbcb580f3f8")]:
LookupFailed:
IncorrectOffset: {
"correct_offset" = 10485760;
}
FINAL APPEND ERROR: Optional([request-id 22682566e018e51de3b0d071d879f0a4] API route error - {
".tag" = "incorrect_offset";
"correct_offset" = 10485760;
})
APPEND ERROR: Optional([request-id c10a9f363552525ddea86a476cb5c921] API route error - {
".tag" = "incorrect_offset";
"correct_offset" = 10485760;
})
APPEND ERROR: Optional([request-id 587f7df38872cc7f3af9fa867646a5d0] API route error - {
".tag" = "incorrect_offset";
"correct_offset" = 10485760;
})

Christian T.16
New member | Level 1

ok, so now i'm playing around with waiting for each append to return before the next one is called and I'm getting successful (void) returns.

Greg-DB
Dropbox Staff

Yes, append calls for a single file's upload session need to be called serially, in order.

Christian T.16
New member | Level 1

Thanks for all your help. I got it working. In case anyone needs sample code, here is how I handle uploading a file by appending 5MB chunks....

 

        let chunkLength:UInt64 = 1024 * 1024 * 5 //in MB

        let fileLength:UInt64 = UInt64(data.length)//Double(data.length)/1024/1024 //in MB

        

        print("FILE LENGTH: \(fileLength)")

        print("CHUNK LENGTH: \(chunkLength)")

        

        if (fileLength < chunkLength) {

            print("LESS THAN CHUNK SIZE")

            //Upload File

            if let client = Dropbox.authorizedClient {

                client.files.upload(path:destinationPath+uploadFilename!, body:data).response { response, error in

                    if let metadata = response {

                        completion()

                    } else {

                        print("UPLOAD ERROR(DropboxUploader.swift): \(error!)")

                    }

                }

            }

            

        } else {

            

            print("MORE THAN CHUNK SIZE")

            

            //var inputStream:NSInputStream = NSInputStream(data: data)

            var startPosition:UInt64 = 0

            var loopCounter:UInt64 = 0

            var tempData:NSData = data

            var range:NSRange = NSMakeRange(Int(startPosition), Int(chunkLength))

            let sem = dispatch_semaphore_create(0)

            let globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

            

            //Upload File

            if let client = Dropbox.authorizedClient {

                

                client.files.uploadSessionStart(body: NSData()).response { response, error in

                    

                    if let result = response {

                        

                        print("UPLOAD SESSION START RESULT: \(result)")

                        var sid = result.sessionId

                        

                        dispatch_async(globalQueue, {

                        

                            while (startPosition <= fileLength) {

                                

                                startPosition = chunkLength*loopCounter

                                

                                if (startPosition >= UInt64(data.length)) {

                                    break

                                }

 

                                if (startPosition+chunkLength >= UInt64(data.length)) {

                                    range = NSMakeRange(Int(startPosition), (data.length)-Int(startPosition))

                                    tempData = data.subdataWithRange(range)

                                } else {

                                    range = NSMakeRange(Int(startPosition), Int(chunkLength))

                                    tempData = data.subdataWithRange(range)

                                }

                                

                                print("\(loopCounter). LOOP COUNTER")

                                print("START POSITION: \(startPosition)")

                                print("RANGE: \(range)")

                                

                                client.files.uploadSessionAppend(sessionId: sid, offset: startPosition, body: tempData).response { response, error in

                                    if let result = response {

                                        print("APPEND RESULT: \(result)\n")

                                        loopCounter++

                                        dispatch_semaphore_signal(sem)

                                    } else {

                                        print("APPEND ERROR: \(error)")

                                    }

                                }

                                

                                dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER)

                                

                            }

                            

                            

                            startPosition = UInt64(data.length)

                            print("UPLOAD SESSION FINISH POSITION \(startPosition)")

                            

                            // we're ready to finish the upload and commit the file

                            client.files.uploadSessionFinish(cursor: Files.UploadSessionCursor(sessionId: sid, offset: startPosition),

                                commit: Files.CommitInfo(path: destinationPath+uploadFilename!),

                                // no additional data to add at this point in this case

                                body:NSData()).response { response, error in

                                    

                                    if let result = response {

                                        print("Result: \(result)")

                                    } else if let callError = error {

                                        print("\(callError)")

                                        switch callError as CallError {

                                        case .RouteError(let boxed, let requestId):

                                            print("RouteError[\(requestId)]:")

                                            switch boxed.unboxed as Files.UploadSessionFinishError {

                                            case .Path(let fileLookupError):

                                                print("Path: ")

                                                switch fileLookupError {

                                                case .MalformedPath(let malformedPathError):

                                                    print("MalformedPath: \(malformedPathError)")

                                                case .Conflict(let writeConflictError):

                                                    print("Conflict:")

                                                    switch writeConflictError {

                                                    case .File:

                                                        print("File")

                                                    case .FileAncestor:

                                                        print("FileAncestor")

                                                    case .Folder:

                                                        print("Folder")

                                                    case .Other:

                                                        print("Other")

                                                    }

                                                case .DisallowedName:

                                                    print("DisallowedName")

                                                case .InsufficientSpace:

                                                    print("InsufficientSpace")

                                                case .NoWritePermission:

                                                    print("NoWritePermission")

                                                case .Other:

                                                    print("Other")

                                                }

                                            case .LookupFailed(let uploadSessionLookupError):

                                                print("LookupFailed:")

                                                switch uploadSessionLookupError {

                                                case .Closed:

                                                    print("Closed")

                                                case .IncorrectOffset(let uploadSessionOffsetError):

                                                    print("IncorrectOffset: \(uploadSessionOffsetError)")

                                                case .NotFound:

                                                    print("NotFound")

                                                case .Other:

                                                    print("Other")

                                                }

                                            case .Other:

                                                print("Other")

                                            }

                                        case .BadInputError(let message, let requestId):

                                            print("BadInputError[\(requestId)]: \(message)")

                                        case .HTTPError(let code, let message, let requestId):

                                            print("HTTPError[\(requestId)]: \(code): \(message)")

                                        case .InternalServerError(let code, let message, let requestId):

                                            print("InternalServerError[\(requestId)]: \(code): \(message)")

                                        case .OSError(let err):

                                            print("OSError: \(err)")

                                        case .RateLimitError:

                                            print("RateLimitError")

                                        }

                                    }

                                    

                            }

 

                            

                        })

 

                                    

 

                    } else {

                        print("UPLOAD SESSION START ERROR(DropboxUploader.swift): \(error!)")

                    }

                }

            }

        }

 

Steve M.
Dropbox Staff

Christian, kudos on getting this working!

See https://gist.github.com/smarx/4bd20487ddf37a5942bf for my quick take on this. The main difference in the structure of my code is that I'm using recursion instead of a while loop. This lets me get rid of the threading and semaphore in your code. I think that my approach is the more natural one when dealing with async callbacks like you'll find throughout SwiftyDropbox. (Note, though, that my error handling is much more primitive than yours!)

Christian T.16
New member | Level 1

Thanks Steve, I too suggested a recursive function solution but my team favored the threading/semaphore route.

Need more support?