You might see that the Dropbox Community team have been busy working on some major updates to the Community itself! So, here is some info on what’s changed, what’s staying the same and what you can expect from the Dropbox Community overall.

Forum Discussion

Bjorn1's avatar
Bjorn1
Explorer | Level 3
8 years ago

Uploading a file to Dropbox in chunks using Objective C

This is maybe a very simple question, but I'm looking for an example how to upload a file to Dropbox using Objective C on iOS. For small files this is rather straightforward, but for large files it's more difficult. Is there any simple example on the web how to use: uploadSessionStart, uploadSessionAppendV2 and uploadSessionFinish?

 

Any ideas welcome!

  • Greg-DB's avatar
    Greg-DB
    Icon for Dropbox Staff rankDropbox Staff

    We don't have an example for using upload sessions in the API v2 Objective-C SDK unfortunately, but I'll pass this along as a request for one.

     

    I have some samples for other languages though, which may still be useful, since the logic is the same.

     

    For example, a simple implementation in Python:

    f = open(file_path)
    file_size = os.path.getsize(file_path)
    
    CHUNK_SIZE = 8 * 1024 * 1024
    
    if file_size <= CHUNK_SIZE:
    
        print dbx.files_upload(f.read(), dest_path)
    
    else:
    
        upload_session_start_result = dbx.files_upload_session_start(f.read(CHUNK_SIZE))
        cursor = dropbox.files.UploadSessionCursor(session_id=upload_session_start_result.session_id,
                                                   offset=f.tell())
        commit = dropbox.files.CommitInfo(path=dest_path)
    
        while f.tell() < file_size:
            if ((file_size - f.tell()) <= CHUNK_SIZE):
                print dbx.files_upload_session_finish(f.read(CHUNK_SIZE),
                                                cursor,
                                                commit)
            else:
                dbx.files_upload_session_append(f.read(CHUNK_SIZE),
                                                cursor.session_id,
                                                cursor.offset)
                cursor.offset = f.tell()
    
    f.close()

    Here's a longer example in Swift that splits out every error case:

     

    import UIKit
    import SwiftyDropbox
    
    class ViewController: UIViewController {
    
        // filled in later in doUpload:
        var fileHandle : NSFileHandle? = nil
        var data : NSData? = nil
    
        let chunkSize = 8 * 1024 * 1024  // 8 MB
        var offset = 0
        var sessionId = ""
    
        // replace this with your desired destination path:
        let destPath = "/SwiftyDropbox_upload.txt"
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            Dropbox.authorizedClient = DropboxClient(...)
    
            doUpload()
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    
        func doUpload() {
    
            // replace this with the path to the file you want to upload
            let filePath = "/path/to/file"
            print("Getting file at \(filePath) for uploading...")
            fileHandle = NSFileHandle.init(forReadingAtPath: filePath)!
    
            print("Using chunked uploading with chunk size \(chunkSize)...")
            uploadFirstChunk()
    
        }
    
        func uploadFirstChunk() {
            data = fileHandle!.readDataOfLength(chunkSize)
            let size = data!.length
            print("Have \(size) bytes to upload.")
            Dropbox.authorizedClient!.files.uploadSessionStart(input:data!)
                .response { response, error in
                    if let result = response {
                        self.sessionId = result.sessionId
                        self.offset += size
                        print("So far \(self.offset) bytes have been uploaded.")
                        self.uploadNextChunk()
                    } else if let callError = error {
                        print("uploadSessionStart failed")
                        switch callError as CallError {
                        case .RouteError(let error, let requestId):
                            print("RouteError[\(requestId)]: \(error)")
                        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")
                        }
                    }
            }
        }
    
        func uploadNextChunk() {
            data = fileHandle!.readDataOfLength(chunkSize)
            let size = data!.length
            print("Have \(size) bytes to upload.")
            if size < chunkSize {
                print("Last chunk!")
                Dropbox.authorizedClient!.files.uploadSessionFinish(
                    cursor: Files.UploadSessionCursor(sessionId: self.sessionId, offset: UInt64(offset)),
                    commit: Files.CommitInfo(path:destPath),
                    input: data!)
                    .response { response, error in
                        if let callError = error {
                            print("uploadSessionFinish failed")
                            switch callError as CallError {
                            case .RouteError(let boxed, let requestId):
                                print("RouteError[\(requestId)]:")
                                switch boxed.unboxed as Files.UploadSessionFinishError {
                                case .Path(let writeError):
                                    print("Path: ")
                                    switch writeError {
                                    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 .NotClosed:
                                        print("NotFound")
                                    case .Other:
                                        print("Other")
                                    }
                                case .TooManySharedFolderTargets:
                                    print("TooManySharedFolderTargets")
                                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 if let result = response {
                            print("Done!")
                            print(result)
                        }
                }
            } else {
                Dropbox.authorizedClient!.files.uploadSessionAppendV2(
                    cursor: Files.UploadSessionCursor(sessionId: self.sessionId, offset: UInt64(offset)),
                    input: data!)
                    .response { response, error in
                        if error == nil {
                            self.offset += self.chunkSize
                            print("So far \(self.offset) bytes have been uploaded.")
                            self.uploadNextChunk()
                        } else if let callError = error {
                            print("uploadSessionAppend failed")
                            switch callError as CallError {
                            case .RouteError(let boxed, let requestId):
                                print("RouteError[\(requestId)]:")
                                switch boxed.unboxed as Files.UploadSessionLookupError {
                                case .Closed:
                                    print("Closed")
                                case .IncorrectOffset(let uploadSessionOffsetError):
                                    print("IncorrectOffset: \(uploadSessionOffsetError)")
                                case .NotFound:
                                    print("NotFound")
                                case .NotClosed:
                                    print("NotClosed")
                                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")
                            }
                        }
                }
            }
        }
    
    }