Returning ENOTCONN Error - ios

Im trying to upload image to Aws S3 bucket. I tried to follow a tutorial and I'm getting a error saying "Returning ENOTCONN because protocol has not yet been set up." I'm new to swift and I'm not able to understand why the error is occurring also.My code for S3 upload is as follows:
let uploadRequest = AWSS3TransferManagerUploadRequest()
uploadRequest?.body = url!
uploadRequest?.key = remoteFileName
uploadRequest?.bucket = S3BucketName
uploadRequest?.contentType = "image/" + ext
let transferManager = AWSS3TransferManager.default()
// Perform Upload
transferManager.upload(uploadRequest!).continueWith(block: { (task:AWSTask<AnyObject>) -> AnyObject! in
if let error = task.error{
print("error \(error.localizedDescription)")
}
if task.result != nil {
let url = AWSS3.default().configuration.endpoint.url
let publicURL = url?.appendingPathComponent((uploadRequest?.bucket!)!).appendingPathComponent((uploadRequest?.key!)!)
print("Uploaded to:\(publicURL)")
}
return nil
})
My S3 is in ap-south-1 and cognito pool id in us-west-2. I guess thats creating the problem.Is there a way to fix the issue without creating another bucket in us-west-2.
I get the following error:

You want the bucket policy to be somewhat like this if the cognito pool is not set up for authentication: Notice Principal and Action values
Also, is there any particular reason you're using AWSS3TransferManagerUploadRequest? If the policy doesn't resolve your issue, you can use the following code for AWSS3TransferUtilityUploadExpression which sends your data in chunks asynchronously.
let expression = AWSS3TransferUtilityUploadExpression()
expression.progressBlock = progressBlock
transferUtility.uploadData(UIImagePNGRepresentation(imageNew!)!,
bucket: "bucket-name",
key: (imgName.removeWhitespace()),
contentType: "image/png",
expression: expression,
completionHandler: completionHandler).continueWith { (task) -> AnyObject! in
if let error = task.error {
print("Error: \(error.localizedDescription)")
}
if let _ = task.result {
print("Upload Starting!")
// Do something with uploadTask.
}
return nil;
}

Related

Set public-read ACL for AWS S3 data upload via iOS Amplify

I've been attempting to upload images to an existing resource in S3, the images need to be publicly viewable and our website expects that the app sets the ACL to public-read on the file.
I have been unable to find a solution using the Amplify SDK that gets this done.
Currently even using the "guest" access level my images are not viewable at their S3 URLS.
Does anyone know how to set the "public-read" ACL during upload using the iOS Amplify SDK?
https://docs.amplify.aws/lib/storage/configureaccess/q/platform/ios/
Have you tried using "protected"?
I was able to hack together something that works for now using the escape hatch of the Amplify SDK.
https://docs.amplify.aws/lib/storage/escapehatch/q/platform/ios/
func uploadToS3(path: URL, data: Data, bucketName: String, uploadKeyName: String, contentType: String) {
do {
let plugin = try Amplify.Storage.getPlugin(for: "awsS3StoragePlugin") as? AWSS3StoragePlugin
if let escapedPlugin = plugin {
let awsS3 = escapedPlugin.getEscapeHatch()
let request = AWSS3PutObjectRequest()
if let req = request {
req.body = data
req.contentType = contentType
req.contentLength = NSNumber(integerLiteral: NSData(data: data).length)
req.bucket = bucketName
req.key = uploadKeyName
req.acl = .publicRead
awsS3.putObject(req).continueWith { (task) -> AnyObject? in
if let error = task.error {
print("there was an error with uploading image \(error)")
}
if task.result != nil {
let s3URL = NSURL(string: "http://s3.amazonaws.com/\(bucketName)/\(uploadKeyName)")
print("Uploaded to:\n\(s3URL)")
}
return nil
}
}
}
} catch {
print("Get escape hatch failed with error - \(error)")
}
}

How to upload multiple docs/pdf files to AWS from iOS application simultaneoulsy

I am fetching multiple files (docs/pdfs) from iCloud/Dropbox to my iOS (Swift) app and trying to uploading them to AWS.
I have seen AWS documentation for uploading the files to AWS one by one (not multiple at a time).
I am trying to uploading multiple files same time to AWS.
I have array which contains multiple document/pdfs paths.
I have seen following code in AWS documentation.
let uploadingFileURL = URL(fileURLWithPath: "your/file/path/myTestFile.txt")
let uploadRequest = AWSS3TransferManagerUploadRequest()
uploadRequest.bucket = "myBucket"
uploadRequest.key = "myTestFile.txt"
uploadRequest.body = uploadingFileURL
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
})
how to move forward on this task?

Amazon AWS server side encryption in ios swift

In my app, I'm uploading the images attached by the user to S3 bucket in which server side encryption is used.
We have used the following code in Android to achieve this and it WORKED.
try
{
SSECustomerKey sseCustomerKey = new SSECustomerKey(BuildConfig.S3_AES_ENCRYPT_KEY);
CognitoCachingCredentialsProvider sCredProvider = new CognitoCachingCredentialsProvider(mContext, AWSCognitoPoolId, Regions.fromName(Regions.US_EAST_1.getName()));
AmazonS3Client sS3Client = new AmazonS3Client(sCredProvider);
PutObjectRequest putRequest = new PutObjectRequest(BuildConfig.S3_BUCKET_NAME, file.getName(), file).withSSECustomerKey(sseCustomerKey);
sS3Client.putObject(putRequest);
sS3Client.setRegion(Region.getRegion(Regions.fromName(Regions.US_EAST_1.getName())));
}
But in iOS, it is not working. Please find the following iOS code.
let transferManager = AWSS3TransferManager.default()
let uploadRequest = AWSS3TransferManagerUploadRequest()
uploadRequest?.bucket = bucketName
uploadRequest?.body = fileURL
uploadRequest?.key = imageName[i]
uploadRequest?.serverSideEncryption = .AES256
uploadRequest?.sseCustomerKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
uploadRequest?.contentType = "image/jpeg"
transferManager.upload(uploadRequest!).continueWith(block: { (task) -> AnyObject? in
if let error = task.error as NSError? {
if error.domain == AWSS3TransferManagerErrorDomain as String {
if let errorCode = AWSS3TransferManagerErrorType(rawValue: error.code) {
switch (errorCode) {
case .cancelled, .paused:
DispatchQueue.main.async {
}
break;
default:
print("upload() failed: [\(error)]")
break;
}
} else {
print("upload() failed: [\(error)]")
}
} else {
print("upload() failed: [\(error)]")
}
}
return nil
})
I get the following error in iOS
upload() failed: [Error Domain=com.amazonaws.AWSS3ErrorDomain Code=0
"(null)" UserInfo={RequestId=C7302D0F4DD27397,
HostId=Dm3itGpwZNcpPq28qfFkKDlB2VFbOzIYn01T270QzzVXJ9lmZWU2bX7oPXyXrG5A86OpfTrXSHw=,
Message=Server Side Encryption with Customer provided key is
incompatible with the encryption method specified,
ArgumentValue=AES256, Code=InvalidArgument,
ArgumentName=x-amz-server-side-encryption}]
Please show me some light on this
I would recommend that you use TransferUtility instead of TransferManager. The TransferManager is on a deprecation path and doesn't have all the features that the TransferUtility has. Here is a code snippet showing how you can upload a file with server side encryption.
let transferUtility = AWSS3TransferUtility.default()
let uploadExpression = AWSS3TransferUtilityUploadExpression()
uploadExpression.setValue("AES256", forRequestHeader: "x-amz-server-side-encryption")
uploadExpression.progressBlock = {(task, progress) in
print("Upload progress: ", progress.fractionCompleted)
}
let uploadCompletionHandler = { (task: AWSS3TransferUtilityUploadTask, error: Error?) -> Void in
if let error = error {
//Error completing transfer. Handle Error
}
else {
//Successfully uploaded.
......
return nil
}
}
transferUtility.uploadData(
data,
bucket: "bucket",
key: "key",
contentType: "contenttype",
expression: uploadExpression,
completionHandler: uploadCompletionHandler
).continueWith (block: { (task) -> Any? in
if let error = task.error {
//Error initiating transfer. Handle error
}
return nil
})
}
Here is a link to more information on how to use TransferUtility - https://docs.aws.amazon.com/aws-mobile/latest/developerguide/how-to-transfer-files-with-transfer-utility.html
Now it's been years but still this answer would help someone and save hours of searching which i have gone through, TransferManager is deprecated so now we are using transferUtility s3 to upload files, But if we want to encrypt the files we have to send 3 keys in the header
expression.setValue("AES256", forRequestHeader: "x-amz-server-side-encryption-customer-algorithm")
expression.setValue(base64String, forRequestHeader: "x-amz-server-side-encryption-customer-key")
expression.setValue(md5String, forRequestHeader: "x-amz-server-side-encryption-customer-key-MD5")
These 3 keys are necessary otherwise the transfer utility won't upload the file and give u an error, x-amz-server-side-encryption-customer-algorithm this key is use to tell which encryption algorithm u want to use, For the other 2 keys we have to generate them, Sample code is this to generate base64String and md5, There are many ways to generate the key you can look at the CryptoSwift docs, I have used Salt which makes it more secure then brute force attacks
let input: Array<UInt8> = [0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9]
let password: [UInt8] = Array("s33krit".utf8)
let salt: [UInt8] = Array("nacllcan".utf8)
let iv: Array<UInt8> = AES.randomIV(AES.blockSize)
DispatchQueue.global().async {
do {
let key = try PKCS5.PBKDF2(password: password, salt: salt, iterations: 4096, keyLength: 32, variant: .sha2(.sha224)).calculate()
let encrypted = try AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7).encrypt(input)
let base64String: String = encrypted.toBase64()
let md5Data = encrypted.md5()
let md5DataBase64 = md5Data.toBase64()
print("Encrypted:\(encrypted),\n Base64String:\(base64String)")
print("md5:\(md5Data),\n md5String:\(md5DataBase64)")
completion(base64String,md5DataBase64)
} catch {
print(error)
}
}
You have to use CryptoSwift to generate these md5 and base64String keys to send in the headers, This will upload the encrypted file to the AWS and to open it or decrypt it you have to use the same base64 key
Hope this will help someone and save hours of time

AWS: DeveloperAuthenticatedIdentityProvider not firing IOS Swift

I am trying to integrate S3 upload to upload a video file and tried Developer authenticated Identity method. Everything is configured as per the aws docs says.
DeveloperAuthenticatedIdentityProvider Class :
class DeveloperAuthenticatedIdentityProvider : AWSCognitoCredentialsProviderHelper {
override func token() -> AWSTask<NSString> {
//return AWSTask //with token and will set identityId
}
and then
let devAuth = DeveloperAuthenticatedIdentityProvider(regionType: COGNITO_REGION, identityPoolId: COGNITO_POOL_ID, useEnhancedFlow: true, identityProviderManager:nil)
let credentialsProvider =
AWSCognitoCredentialsProvider(regionType: COGNITO_REGION, identityProvider:devAuth)
let configuration =
AWSServiceConfiguration(region: S3_REGION, credentialsProvider:credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
after configuring these things tried to upload using AWSS3TransferManager
let transferManager = AWSS3TransferManager.default()
let uploadingFileURL = URL(fileURLWithPath: "your/file/path/myTestFile.txt")
let uploadRequest = AWSS3TransferManagerUploadRequest()
uploadRequest.bucket = "myBucket"
uploadRequest.key = "myTestFile.txt"
uploadRequest.body = uploadingFileURL
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
})
Whenever I call Upload method it shows
[Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=8
"(null)" UserInfo={__type=NotAuthorizedException,
message=Unauthenticated access is not supported for this identity
pool.}]
also DeveloperAuthenticatedIdentityProvider not getting fired
kindly please help.
When you using Developer authenticated identity for cognito identity provider you need not use
AWSS3TransferManager.default()
You need to register the AWSServiceConfiguration to the AWSS3TransferManager with a key.
AWSS3TransferManager.register(with: configuration!, forKey:
"KEY")
Try this way:
let devAuth = DeveloperAuthenticatedIdentityProvider(regionType: COGNITO_REGION, identityPoolId: COGNITO_POOL_ID, useEnhancedFlow: true, identityProviderManager:nil)
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: COGNITO_REGION, identityProvider:devAuth)
let configuration = AWSServiceConfiguration(region: S3_REGION, credentialsProvider:credentialsProvider)
AWSS3TransferManager.register(with: configuration!, forKey: "YOUR_KEY")
//Start Upload
let uploadRequest = AWSS3TransferManagerUploadRequest()
//Set all properties to uploadRequest
AWSS3TransferManager.s3TransferManager(forKey: "YOUR_KEY").upload(uploadRequest!).continueWith(executor: AWSExecutor.mainThread(), block: { (task:AWSTask<AnyObject>) -> Any? in
// Do something with the response
if task.isCancelled {
print("Cancelled Upload")
}
else if (task.error != nil) {
print("Upload error --> \(task.error)")
}else{
print("Upload success!!! Be happy :)")
}
return task
})
Just try, I think it may work.

Application getting crashed at upload image in AWS S3 bucket for swift 3

In my application, I am trying to upload image using AWS S3. But, When i am selecting image from library or captured image,in uploading process my application is getting crashed.
let path:NSString = (NSTemporaryDirectory() as NSString).appendingPathComponent("testImage.png") as NSString
let imageData:NSData = UIImagePNGRepresentation(image)! as NSData
imageData.write(toFile: path as String, atomically: true)
let url:NSURL = NSURL(fileURLWithPath: path as String)
let expression = AWSS3TransferUtilityUploadExpression()
expression.setValue("public-read", forRequestParameter: "x-amz-acl")
expression.setValue("public-read", forRequestHeader: "x-amz-acl" )
let transferUtility = AWSS3TransferUtility.default()
transferUtility.uploadFile(url as URL!, bucket: bucketURL, key: myImageUploadKey , contentType: "image/png", expression: expression, completionHandler: { (task, error) in
if error != nil{
print(error?.localizedDescription ?? "error")
}else{
print(task.response ?? "Response error")
}
})
expression.progressBlock = { (task: AWSS3TransferUtilityTask, progress: Progress) in
print("progress \(progress.fractionCompleted)")
}
application is getting crashed at let transferUtility = AWSS3TransferUtility.default()
So please suggest any solution. It will be highly appreciated.Thanks.
May be this issue is coming due to AWS S3 pod updation. Please check the latest pods. Please check out this https://github.com/aws/aws-sdk-ios

Resources