iosswiftamazon-web-servicesamazon-s3awss3transfermanager

Upload jpg to S3: "The request body terminated unexpectedly"


I am facing an issue with S3. After 3h of troubleshooting (in the meantime i learnt about IAM roles & managed to create them) I am stuck trying to upload a fb profile picture to amazon S3.

My code:

if let imageData = NSData(contentsOf: NSURL(string: url) as! URL) {

                            let fileName = ProcessInfo.processInfo.globallyUniqueString + ".jpg"
                            let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(fileName)
                            let image = UIImage(data: imageData as Data)
                            let imageData = UIImageJPEGRepresentation(image!, 1.0)!
                            do {
                                try imageData.write(to: fileURL! as URL)
                            } catch _ {
                                self.log.error("Could not write to file.")
                            }

                            let transferManager = AWSS3TransferManager.default()
                            let uploadRequest = AWSS3TransferManagerUploadRequest()
                            uploadRequest?.bucket = "app-files"
                            uploadRequest?.key = "user-data/" + awsId! + "_primary_profile_picture.jpg"
                            uploadRequest?.body = fileURL!

                            transferManager.upload(uploadRequest!).continueWith(executor: AWSExecutor.mainThread(), block: { (task:AWSTask<AnyObject>) -> Any? in

                                if let error = task.error as? NSError {
                                    if error.domain == AWSS3TransferManagerErrorDomain, let code = AWSS3TransferManagerErrorType(rawValue: error.code) {
                                        switch code {
                                        case .cancelled, .paused:
                                            break
                                        default:
                                            print("Error uploading: \(uploadRequest?.key) Error: \(error)")
                                        }
                                    } else {
                                        print("Error uploading: \(uploadRequest?.key) Error: \(error)")
                                    }
                                    return nil
                                }

                                let uploadOutput = task.result
                                print("Upload complete for: \(uploadRequest?.key)")
                                return nil
                            })
                        }

**Problem** I am continuously getting a The request body terminated unexpectedly error from S3 which looks like this:

Error uploading: Optional("user-data/eu-west-1:xxxx-xxxx-xxxx-xxxx-xxxxxxxxxx_primary_profile_picture.jpg") 
Error: Error Domain=com.amazonaws.AWSS3ErrorDomain Code=0 "(null)" 
UserInfo={HostId=XXX, 
Message=The request body terminated unexpectedly, 
Code=IncompleteBody, 
RequestId=1485A0FFBD7819D7}

I am not sure what is going wrong, i have debugged, and fileName, fileURL, imageData seem to be fine


Solution

  • There is a bug with the 2.5.1 SDK, I explain a bit about it here.

    Basically, the AWSSignature creates the wrong signature for the upload...

    You have two ways to get around it:

    1) Revert to using 2.5.0 by declaring all the pods you need explicitly like so: (Edit: I just noticed you can't do that because of the SWIFT problem. Try option 2 maybe)

    pod 'AWSCore', '2.5.0'
    pod 'AWSCognito', '2.5.0'
    pod 'AWSLambda', '2.5.0'
    pod 'AWSSNS', '2.5.0'
    pod 'AWSS3', '2.5.0'
    

    2) Change the code yourself to fix the problem until Amazon fix it. All you need to do is comment out lines 783-785 in the AWSCore/Authentication/AWSSignature.m file - you should get a message that the file is locked if you try, just unlock it.

    if (self.endOfStream) {
        return NO;
    }