swiftfile-uploadamazon-s3

amazon S3 Swift - simple upload take ages and finally doesnt show up in bucket


I m trying to send a photo on an S3 bucket. Well, this is hell of undocumented in swift, and sdks are fragmented here and there, it s a big mess on my side and nothing works so far :

My uploading process goes on, but extremely slow (let s say a 5 meg image takes 10 minutes) and most of the time, the upload freezes and starts over again.

But the weird thing is when It finally succeeds, the file doesn t show up in my bucket. I ve tried uploading files to non existing buckets and the process still goes on (???)

here are my credentials loc (bucket is in east california)

        let credentialsProvider = AWSCognitoCredentialsProvider(
        regionType: AWSRegionType.USEast1, identityPoolId: "us-east-1:47e88493-xxxx-xxxx-xxxx-xxxxxxxxx")

    let defaultServiceConfiguration = AWSServiceConfiguration(
        region: AWSRegionType.USEast1, credentialsProvider: credentialsProvider)

    AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = defaultServiceConfiguration

now here s my upload function

func uploadImage(){

        //defining bucket and upload file name
        let S3BucketName: String = "witnesstestbucket"
        let S3UploadKeyName: String = "public/testImage.jpg"


        let expression = AWSS3TransferUtilityUploadExpression()
        expression.uploadProgress = {(task: AWSS3TransferUtilityTask, bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) in
            dispatch_async(dispatch_get_main_queue(), {
                let progress = Float(totalBytesSent) / Float(totalBytesExpectedToSend)
                print("Progress is: \(progress)")
                print (Float(totalBytesExpectedToSend))

            })
        }

        self.uploadCompletionHandler = { (task, error) -> Void in
            dispatch_async(dispatch_get_main_queue(), {
                if ((error) != nil){
                    print("Failed with error")
                    print("Error: \(error!)");
                }
                else{
                    print("Sucess")
                }
            })
        }

        let transferUtility = AWSS3TransferUtility.defaultS3TransferUtility()

        transferUtility.uploadData(imagedata, bucket: S3BucketName, key: S3UploadKeyName, contentType: "image/jpeg", expression: expression, completionHander: uploadCompletionHandler).continueWithBlock { (task) -> AnyObject! in
            if let error = task.error {
                print("Error: \(error.localizedDescription)")
            }
            if let exception = task.exception {
                print("Exception: \(exception.description)")
            }
            if let _ = task.result {
                print("Upload Starting!")
            }

            return nil;
        }
}






@IBAction func post(sender: UIButton) {
    // AW S3 upload


    uploadImage()

}

to make it clear, My imagedata NSData comes from a uiimage, fetched from a collectionviewcell:

 self.imagedata = UIImageJPEGRepresentation(img!, 05.0)!

Is there anything I could update to understand where I am wrong ? thanks in advance :)


Solution

  • ok, was trying to upload NSData file using the uploaddata request, here is the working code with proper URL swift2 conversion :

     func uploadImage(){
    
            let img:UIImage = fullimage!.image!
    
            // create a local image that we can use to upload to s3
            let path:NSString = NSTemporaryDirectory().stringByAppendingString("image2.jpg")
            let imageD:NSData = UIImageJPEGRepresentation(img, 0.2)!
            imageD.writeToFile(path as String, atomically: true)
    
            // once the image is saved we can use the path to create a local fileurl
            let url:NSURL = NSURL(fileURLWithPath: path as String)
    
            // next we set up the S3 upload request manager
            uploadRequest = AWSS3TransferManagerUploadRequest()
            // set the bucket
            uploadRequest?.bucket = "witnesstest"
            // I want this image to be public to anyone to view it so I'm setting it to Public Read
            uploadRequest?.ACL = AWSS3ObjectCannedACL.PublicRead
            // set the image's name that will be used on the s3 server. I am also creating a folder to place the image in
            uploadRequest?.key = "foldername/image2.jpeg"
            // set the content type
            uploadRequest?.contentType = "image/jpeg"
            // and finally set the body to the local file path
            uploadRequest?.body = url;
    
            // we will track progress through an AWSNetworkingUploadProgressBlock
            uploadRequest?.uploadProgress = {[unowned self](bytesSent:Int64, totalBytesSent:Int64, totalBytesExpectedToSend:Int64) in
    
                dispatch_sync(dispatch_get_main_queue(), { () -> Void in
                    self.amountUploaded = totalBytesSent
                    self.filesize = totalBytesExpectedToSend;
                    print(self.filesize)
                    print(self.amountUploaded)
                })
            }
    
            // now the upload request is set up we can creat the transfermanger, the credentials are already set up in the app delegate
            let transferManager:AWSS3TransferManager = AWSS3TransferManager.defaultS3TransferManager()
            // start the upload
    
            transferManager.upload(uploadRequest).continueWithBlock { (task) -> AnyObject? in
    
    
                // once the uploadmanager finishes check if there were any errors
                if(task.error != nil){
                    print("%@", task.error);
                }else{ // if there aren't any then the image is uploaded!
                    // this is the url of the image we just uploaded
                    print("https://s3.amazonaws.com/witnesstest/foldername/image2.jpeg");
                }
    
                return "all done";
                }
    
    }
    

    I would like to thank Barrett Breshears for the Help, and his GithubSource is from 2014 but I could manage to convert it easily because of this clear and well commented piece of code