AWSS3TransferUtilityErrorDomain Code=2 on iOS Swift While trying to upload Image/pdf - ios

I am trying to upload pdf file or image file to AWSS3 bucket but I am getting AWSS3TransferUtilityErrorDomain Code=2 error. Please note I already have checked region and it is correct. Also I have verified that I am using correct accessKey and secretKey I also have visited below mentioned links with no luck:
(https://github.com/aws-amplify/aws-sdk-ios/issues/2553.)
(https://github.com/aws-amplify/aws-sdk-ios/issues/604)
(https://github.com/aws-amplify/aws-sdk-ios/issues/420)
(https://github.com/aws-amplify/aws-sdk-ios/issues/103)
(Upload image to S3 with Amazon Educate Starter Account)
(About permission in S3 file transfer)
(Swift iOS: Unable to Upload Image to AWS S3)
(AWSS3TransferUtilityErrorDomain Code=2 on ios)
My code to upload file is below:
let credentials = AWSStaticCredentialsProvider(accessKey: “accessKey” , secretKey: “secretKey”)
let configuration = AWSServiceConfiguration(region: AWSRegionType.APSouth1 , credentialsProvider: credentials)
AWSServiceManager.default().defaultServiceConfiguration = configuration
let expression = AWSS3TransferUtilityUploadExpression()
expression.progressBlock = { (task, progress) in
DispatchQueue.main.async(execute: {
// Update a progress bar
print("Task: \(task)")
print("Progress: \(progress)")
})
}
var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
completionHandler = { (task, error) -> Void in
DispatchQueue.main.async(execute: {
if let error = error {
CommonLoader.hide()
SCLAlertView().showError("Error", subTitle: error.localizedDescription)
return
}
// Do stuff after success
})
}
let transferUtility = AWSS3TransferUtility.default()
// contentType —-> “image/jpeg” for images && “application/pdf” for pdf files
transferUtility.uploadData(data, bucket: s3BucketName, key: remoteName, contentType: contentType, expression: expression, completionHandler: completionHandler).continueWith { (task) -> Any? in
if let error = task.error {
// error case
}
else {
if !task.isFaulted && task.result != nil {
// success case
}
}
return nil
}

After a lot of search and reading documentation I am able to solve this issue.
In my case there were two strange things, one with same credentials and bucket on Android it was working.
But on iOS exactly same code was working in Dubai but not in Pakistan.
I solved the issue by just adding the region to project info.plist file as mentioned below:
Please note in my case region was ap-south-1 but you need to put it here yours, you can check region from Amazon S3 Endpoints and then find corresponding region value to use in your info.plist. Hope this will help someone and save time. Happy coding. cheers!
<key>S3TransferUtility</key>
<dict>
<key>Default</key>
<dict>
<key>Region</key>
<string>"ap-south-1"</string>
</dict>
</dict>

Related

Not able to upload more then 5GB video file into AWS S3 bucket

I’m using AWS to upload videos from my App.
I can able to upload up to 5 GB single video without any problem with AWSS3TransferUtilityTask.
My requirement is I want to upload more than 5 gb video file.(e.g 7GB, 10GB , 13GB)
I’ve tried with AWSS3TransferUtilityMultiPartUploadTask to upload more then 5 gb files. After completing more then 60% of upload I'm getting an error (NSURLErrorDomain error -1001).
// Completion Handler
let completionHandler : AWSS3TransferUtilityMultiPartUploadCompletionHandlerBlock? =
{ (task, error) -> Void in
if ((error) != nil)
{
print("------------------>",error?.localizedDescription ?? "")
}
else
{
print("File uploaded successfully")
}
}
//Expression
let expression = AWSS3TransferUtilityMultiPartUploadExpression()
expression.progressBlock = progress
//Content Type
let contentType = "video/mp4"
let transferUtility = AWSS3TransferUtility.default()
transferUtility.uploadUsingMultiPart(fileURL: uploadingFileURL, bucket: bucket, key: path + filename, contentType: contentType, expression: expression, completionHandler: completionHandler)
}
else {
print(" session out----->",jsonData)
}
Thanks in advance.

Process for uploading image to s3 with AWS Appsync || iOS image uploading with Appsync

I'm working on a new project that requires uploading attachments in the form of images. I'm using DynamoDB and AppSync API's to insert and retrieve data from database. As we are new to the AppSync and all the amazon services and database we are using for the app i'm little bit confused about the authentication process. Right now we are using API key for authentication and I have tried these steps to upload image to s3.
1 Configue the AWSServiceManager with static configuration like :-
let staticCredit = AWSStaticCredentialsProvider(accessKey: kAppSyncAccessKey, secretKey: kAppSyncSecretKey)
let AppSyncRegion: AWSRegionType = .USEast2
let config = AWSServiceConfiguration(region: AppSyncRegion, credentialsProvider: staticCredit)
AWSServiceManager.default().defaultServiceConfiguration = config
2 Uploading picture with this method : -
func updatePictureToServer(url:URL, completion:#escaping (Bool)->Void){
let transferManager = AWSS3TransferManager.default()
let uploadingFileURL = url
let uploadRequest = AWSS3TransferManagerUploadRequest()
let userBucket = String(format: "BUCKET")
uploadRequest?.bucket = userBucket
let fileName = String(format: "%#%#", AppSettings.getUserId(),".jpg")
uploadRequest?.key = fileName
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: \(String(describing: uploadRequest!.key)) Error: \(error)")
}
} else {
print("Error uploading: \(String(describing: uploadRequest!.key)) Error: \(error)")
}
completion(false)
return nil
}
_ = task.result
completion(true)
print("Upload complete for: \(String(describing: uploadRequest!.key))")
return nil
})
}
3 And finally i'm able to see the uploaded image on the S3 bucket
But i'm concerned about how to save the url of the image and how to retrieve the image because when i have to make the buket PUBLIC to retrieve the image and i don't think that's a good approach, plus is it necessary to have a Cognito user pool because we aren't using Cognito user pool yet in our app and not have much knowledge about that too and documents are not helping in practical situations because we are implementing ti for the first time so we need some little help.
So two question : -
Proper procedure to use for uploading and retrieving images for S3 and AppSync.
Is it necessary to use Cognito user pool for image uploading and retrieving.
Thanks
Note: Any suggestion or improvement or anything related to the AppSync, S3 or DynamoDB will be truly appreciated and language is not a barrier just looking for directions so swift or objective-c no problem.
You need per-identity security on the bucket using Cognito Federated Identities which gives each user their own secure bucket. You can leverage the AWS Amplify to set this up for your project with $amplify add auth and selecting the default config, then $amplify add storage which configures that bucket and pool with appropriate permissions to use private uploads.
For more info checkout the repo: https://github.com/aws-amplify/amplify-cli

How to upload a video from iOS photo album to Azure Blob Storage

I am struggling with uploading videos from iOS photo album to Azure blob storage. I am using AZSClient.
uploading images is straight forward, ie. I get the image 'Data' from PHAsset and then upload it to azure storage using AZSCloudBlockBlob.uploadFromData method
Can anyone guide me on how to upload a video to azure blob preferably in swift
There was a similar thread for this they used the bellow code, and they used the IOS library found here:
//Upload to Azure Blob Storage with help of SAS
func uploadBlobSAS(container: String, sas: String, blockname: String, fromfile: String ){
// If using a SAS token, fill it in here. If using Shared Key access, comment out the following line.
var containerURL = "https://yourblobstorage.blob.core.windows.net/\(container)\(sas)" //here we have to append sas string: + sas
print("containerURL with SAS: \(containerURL) ")
var container : AZSCloudBlobContainer
var error: NSError?
container = AZSCloudBlobContainer(url: NSURL(string: containerURL)! as URL, error: &error)
if ((error) != nil) {
print("Error in creating blob container object. Error code = %ld, error domain = %#, error userinfo = %#", error!.code, error!.domain, error!.userInfo);
}
else {
let blob = container.blockBlobReference(fromName: blockname)
blob.uploadFromFile(withPath: fromfile, completionHandler: {(NSError) -> Void in
NSLog("Ok, uploaded !")
})
}
}
I found the answer in this thread
let manager = PHImageManager.default()
manager.requestAVAsset(forVideo: asset, options: nil, resultHandler: { (avasset, audio, info) in
if let avassetURL = avasset as? AVURLAsset {
guard let video = try? Data(contentsOf: avassetURL.url) else {
return
}
videoData = video
}
})
once you get the Data object then you can use AZSCloudBlockBlob.uploadFromData to upload it to azure storage

Unable save large file to S3 using Parse server

I tried to save to S3 bucket using Parse Server, and it can be saved correctly when the file is small, such as 864.2KB. However, when the file is large, say 5MB, it complaints with a message saying: "The data couldn’t be read because it isn’t in the correct format"
I'm using the following code to save the the video file to the S3
func saveVideo(withVideoURL url: URL){
let post = PFObject(className: "Post")
post["caption"] = "Out of the game for 6 months, but back with vengeance. Meet your 2017 AO Men's champion"
do{
let data = try Data(contentsOf: url)
print(data)
post["media"] = PFFile(data: data)
post.saveInBackground { (success, error) in
if success{
print("video saved")
}else{
print("failed")
if error != nil{
print(error!.localizedDescription)
}else{
print("erorr is nil")
}
}
}
}catch let error as NSError{
print("can't read")
print(error.localizedDescription)
}
}
Besides, even when the small video file is indeed being saved to the S3, it contains an extension .bin instead of, for example .mp4. I wonder what's happening here
The url end up looking something like this
https://s3-us-west-1.amazonaws.com/sampleApp/19d5bce20f8b55te1b1b8f370212533e5_file.bin
You need to stipulate the content type. You can do so like this:
post["media"] = PFFile(data: data, contentType: "video/mp4")
The below settings in your parse-server index file will help you:
var bodyParser = require('body-parser');
app.use(bodyParser.json({limit: '20mb'}));
app.use(bodyParser.urlencoded({limit: '20mb', extended: true}));
If you are using elastic beanstalk, you have to have a file named files.config inside the folder .ebextensions, with the below content.
files:
/etc/nginx/conf.d/proxy.conf:
content: |
client_max_body_size 20M;
This fixed the issue for me.

Uploading Image to S3 fails to complete upload

I'm uploading an image to S3 and am having trouble completing the file transfer. Here is how the app acts.
Initiate uploadToS3()
File begins transfer sending bytes to server.
When around 600,000 bytes are sent, the upload halts.
After 20-40 seconds, the app continues its upload progress at 0%. It acts as if the file transfer never began in the first place.
During this entire time no errors appear in the logger.
In my view controller I have the following method that uploads the file.
func uploadToS3(){
// get the image from a UIImageView that is displaying the selected Image
var img: UIImage = imageView.image!
// create a local image that we can use to upload to s3
var path: NSString = NSTemporaryDirectory().stringByAppendingPathComponent("image.png")
var imageData: NSData = UIImagePNGRepresentation(img)
imageData.writeToFile(path as String, atomically: true)
// once the image is saved we can use the path to create a local fileurl
var url:NSURL = NSURL(fileURLWithPath: path as String)!
// next we set up the S3 upload request manager
let uploadRequest = AWSS3TransferManagerUploadRequest()
// set the bucket
uploadRequest?.bucket = "test-bucket"
// 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/image.png"
// set the content type
uploadRequest?.contentType = "image/png"
// 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
println("total bytes sent")
println(totalBytesSent)
println("total bytes expected to send")
println(totalBytesExpectedToSend)
})
}
// now the upload request is set up we can creat the transfermanger, the credentials are already set up in the app delegate
var transferManager:AWSS3TransferManager = AWSS3TransferManager.defaultS3TransferManager()
// start the upload
transferManager.upload(uploadRequest).continueWithExecutor(BFExecutor.mainThreadExecutor(), withBlock:{ [unowned self]
task -> AnyObject in
// once the uploadmanager finishes check if there were any errors
if(task.error != nil){
println("%#", task.error);
}else{ // if there aren't any then the image is uploaded!
// this is the url of the image we just uploaded
println("https://s3.amazonaws.com/s3-demo-swift/foldername/image.png");
}
//self.removeLoadingView()
println("all done");
return ""
})
}
For anyone looking to recreate this app
Add to your Podfile:
pod 'AWSCore'
pod 'AWSS3'
pod 'AWSiOSSDKv2'
pod 'AWSCognitoSync'
Then add a bridge header containing:
#import <AWSCore/AWSCore.h>
#import <AWSS3/AWSS3.h>
In my AppDelegate I have:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
AWSCognitoCredentialsProvider.initialize()
var credentialsProvider = AWSCognitoCredentialsProvider(
regionType: AWSRegionType.USEast1,
identityPoolId: "identity pool id"
)
var configuration = AWSServiceConfiguration(
region: AWSRegionType.USEast1,
credentialsProvider: credentialsProvider
)
AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration
return true
}
Finally, in the view controller that contains uploadToS3(), add import AWSS3.
Update
Here is the last section of logged errors.
}]
2015-05-09 19:24:24.540 CoolApp[4492:55681] AWSiOSSDKv2 [Verbose] AWSURLResponseSerialization.m line:278 | -[AWSXMLResponseSerializer responseObjectForResponse:originalRequest:currentRequest:data:error:] | Response body: [<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>A03D405FC272808A</RequestId><HostId>bhSw+xQkGrMVd9QWMKMG1qYezPJet8b5L2ZIoGXePoftuupMP3HdgbAgCpStiLefo5yA3m1OJvY=</HostId></Error>]
(%#, Error Domain=com.amazonaws.AWSS3ErrorDomain Code=1 "The operation couldn’t be completed. (com.amazonaws.AWSS3ErrorDomain error 1.)" UserInfo=0x7c17cdc0 {HostId=bhSw+xQkGrMVd9QWMKMG1qYezPJet8b5L2ZIoGXePoftuupMP3HdgbAgCpStiLefo5yA3m1OJvY=, Code=AccessDenied, Message=Access Denied, RequestId=A03D405FC272808A})
all done
My question is, how do I fix this and have the image upload succesfully.
As the error message states, the permission is not set up correctly with your Amazon Cognito Identity pool. Understanding Amazon Cognito Authentication blog series (Part 2, Part 3) and Amazon Cognito Developer Guide are your great resources for understanding and setting up Cognito Identity.

Resources