Search code examples
sqlitefile-uploadswift3alamofire

Alamofire v4, Swift v3 Uploading Sqlite file to domain


I’m trying to upload an Sqlite database from IOS Swift 3 to my server using Alamofire 4.0, but having problems converting the sqlite file into the data type required to upload.

The majority of posts / question examples seem to default to uploading images, but I am struggling to find example of uploading sqlite or other file types (for back-up purposes)

I have searched for the basic code and found this so far which looks very reasonable (thanks to following post: Alamofire 4 upload with parameters)

let parameters = ["file_name": "swift_file.jpeg"]

Alamofire.upload(multipartFormData: { (multipartFormData) in
    multipartFormData.append(UIImageJPEGRepresentation(self.photoImageView.image!, 1)!, withName: "photo_path", fileName: "swift_file.jpeg", mimeType: "image/jpeg")
    for (key, value) in parameters {
        multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key)
    }
}, to:"http://sample.com/upload_img.php")
{ (result) in
    switch result 
    {
    case .success(let upload, _, _):
    upload.uploadProgress(closure: { (progress) in
        //Print progress
    })
    upload.responseJSON { response in
        //print response.result
    }
    case .failure(let encodingError):
    //print encodingError.description
    }
}

The part I’m struggling with is to append the sqlite file to the upload (multipartFormData.append(………..?) I’ve searched but not found any good reference posts.

Yes, i’m a newbe, but trying hard, any help would be appreciated…..


Solution

  • It's exactly the same as the image example except that the mime type would be application/octet-stream.

    Also, you'd probably go ahead and load it directly from the fileURL rather than loading it into a Data first.

    As an aside, the parameters in that example don't quite make sense, as it looks redundant with the filename provided in the upload of the image itself. So you'd use whatever parameters your web service requires, if any. If you have no additional parameters, you'd simply omit the for (key, value) { ... } loop entirely.

    Finally, obviously replace the file field name with whatever field name your web service is looking for.

    // any additional parameters that must be included in the request (if any)
    
    let parameters = ["somekey": "somevalue"]
    
    // database to be uploaded; I'm assuming it's in Documents, but perhaps you have it elsewhere, so build the URL appropriately for where the file is
    
    let filename = "test.sqlite"
    let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
        .appendingPathComponent(filename)
    
    // now initiate request
    
    Alamofire.upload(multipartFormData: { multipartFormData in
        multipartFormData.append(fileURL, withName: "file", fileName: filename, mimeType: "application/octet-stream")
    
        for (key, value) in parameters {
            multipartFormData.append(value.data(using: .utf8)!, withName: key)
        }
    }, to: urlString) { result in
        switch result {
        case .success(let upload, _, _):
            upload
                .authenticate(user: self.user, password: self.password)   // only needed if you're doing server authentication
                .uploadProgress { progress in
                    print(progress.fractionCompleted)
                }
                .responseJSON { response in
                    print("\(response.result.value)")
            }
        case .failure(let encodingError):
            print(encodingError.localizedDescription)
        }
    }
    

    Unrelated, but if you're ever unsure as to what mime type to use, you can use this routine, which will try to determine mime type from the file extension.

    /// Determine mime type on the basis of extension of a file.
    ///
    /// This requires MobileCoreServices framework.
    ///
    /// - parameter url:  The file `URL` of the local file for which we are going to determine the mime type.
    ///
    /// - returns:        Returns the mime type if successful. Returns application/octet-stream if unable to determine mime type.
    
    func mimeType(for url: URL) -> String {
        let pathExtension = url.pathExtension
    
        if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as NSString, nil)?.takeRetainedValue() {
            if let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() {
                return mimetype as String
            }
        }
        return "application/octet-stream";
    }