cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Announcements
If you're up against the clock to get holiday ready, so here are some tips on how to use Dropbox to make your prep easy! Check them out!

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

Re: parsing upload session finish error

Greg-DB
Dropboxer

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.

Re: parsing upload session finish error

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.

Re: parsing upload session finish error

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;
})

Re: parsing upload session finish error

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.

Re: parsing upload session finish error

Greg-DB
Dropboxer

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

Re: parsing upload session finish error

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!)")

                    }

                }

            }

        }

 

Re: parsing upload session finish error

Steve M.
Dropboxer

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!)

Re: parsing upload session finish error

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?