I just want to upload an image to S3, but I am using AWS Educate Account and I'm trying since 4 hours to get this done and have ZERO ideas what isn't working correctly.
So I've set up everything on the AWS console and the bucket is public to EVERYONE + Region US West N.Virginia like it should be with AWS Educate Accounts.
So here is my code:
let accessKey = "accessKey"
let secretKey = "secretKey"
let credentialsProvider = AWSStaticCredentialsProvider(accessKey: accessKey, secretKey: secretKey)
let configuration = AWSServiceConfiguration(region: AWSRegionType.USEast1, credentialsProvider: credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
let transferUtility = AWSS3TransferUtility.default()
let bucketname = "bucketname"
let expression = AWSS3TransferUtilityUploadExpression()
transferUtility.uploadData(jpegData, bucket: bucketname, key: "myTransferUtilityUpload.jpg", contentType: "image/jpg", expression: expression) { (task, error) in
if let error = error {
print(error.localizedDescription)
}
if let response = task.response {
print(response)
}
}
Can anyone tell me what I do wrong?
I get this error message:
The operation couldn’t be completed.
(com.amazonaws.AWSS3TransferUtilityErrorDomain error 2.)
accessKey + secretKey I got from Account Details + AWS CLI on the 'Welcome to AWS Educate Starter Account' Dashboard and obviously the bucket name is the same name like in my console
EDIT:
if let jpegData = image.jpegData(compressionQuality: 0.7) {
let fileManager = FileManager.default
if let documentDirectory = fileManager.urls(for: .documentDirectory,
in: .userDomainMask).first {
var sourceFolderURL = documentDirectory.appendingPathComponent("image.jpg")
do {
try jpegData.write(to: sourceFolderURL)
} catch {
print(error.localizedDescription)
completionHandler(nil)
return
}
let accessKey = "-"
let secretKey = "-"
let bucketname = "-"
let credentialsProvider = AWSStaticCredentialsProvider(accessKey: accessKey, secretKey: secretKey)
let configuration = AWSServiceConfiguration(region: AWSRegionType.USEast1, credentialsProvider: credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
let uploadRequest = AWSS3TransferManagerUploadRequest()!
uploadRequest.body = sourceFolderURL
uploadRequest.key = "image.jpg"
uploadRequest.bucket = bucketname
uploadRequest.contentType = "image/jpeg"
uploadRequest.acl = .publicReadWrite
let transferManager = AWSS3TransferManager.default()
transferManager.upload(uploadRequest).continueWith { [weak self] (task) -> Any? in
if let error = task.error {
print("Upload failed with error: (\(error.localizedDescription))")
completionHandler(nil)
return nil
}
if task.result != nil {
let url = AWSS3.default().configuration.endpoint.url
let publicURL = url?.appendingPathComponent(uploadRequest.bucket!).appendingPathComponent(uploadRequest.key!)
if let absoluteString = publicURL?.absoluteString {
print("Uploaded to:\(absoluteString)")
completionHandler(nil)
}
}
completionHandler(nil)
return nil
}
}
}
I have uploaded an image to S3 bucket with the following code:
First, save the image to a temporary directory.
func uploadImageToS3(imageName:String, completion:#escaping (Bool) -> Void) {
let accessKey = "accessKey"
let secretKey = "secretKey"
let credentialsProvider = AWSStaticCredentialsProvider(accessKey: accessKey, secretKey: secretKey)
let configuration = AWSServiceConfiguration(region:AWSRegionType.APSoutheast2, credentialsProvider:credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
let S3BucketName = "bucketname"
let uploadRequest = AWSS3TransferManagerUploadRequest()!
uploadRequest.body = self.getImageURLWithName(imageName:imageName)
uploadRequest.key = "\(imageName)"
uploadRequest.bucket = S3BucketName
uploadRequest.contentType = "image/jpeg"
//You can specify private or public here
uploadRequest.acl = .private
let transferManager = AWSS3TransferManager.default()
transferManager.upload(uploadRequest).continueWith { [weak self] (task) -> Any? in
ProgressIndicatorHelper.hideGlobalHUD()
if let error = task.error {
print("Upload failed with error: (\(error.localizedDescription))")
completion(false)
}
if task.result != nil {
let url = AWSS3.default().configuration.endpoint.url
let publicURL = url?.appendingPathComponent(uploadRequest.bucket!).appendingPathComponent(uploadRequest.key!)
if let absoluteString = publicURL?.absoluteString {
print("Uploaded to:\(absoluteString)")
completion(true)
}
}
return nil
}
}
For getting image from Path following code I have used:
func getImageURLWithName(imageName:String) -> URL {
var sourceImageURL: URL!
let fileManager = FileManager.default
if let documentDirectory = fileManager.urls(for: .documentDirectory,
in: .userDomainMask).first {
var sourceFolderURL:URL!
sourceFolderURL = documentDirectory.appendingPathComponent("YourTempFolder")
sourceImageURL = sourceFolderURL.appendingPathComponent(imageName)
}
return sourceImageURL
}
Hope this helps.
Moreover: Right now I don't think you can directly upload image from memory.
I searched for it. Following are links for same:
https://github.com/aws-amplify/aws-sdk-ios/issues/42
How to upload a UIImage to S3 with AWS iOS SDK v2
Let me know if you find any error.
Maybe it's a policy issue?
Try attaching this policy to your bucket (bucket policies)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::mybucketname/*"
]
}
]
}
Related
I am trying to use the AWS S3 bucket to store user photos from when they have taken them from their phones. I right now have my code set up to the point where the user is able to take a photo of something and have that show up on the UIImageView.
The issue I am encountering is that I have no clue how to store it on the S3 bucket, I have code right now that is able to store a specified photo the bucket, but not really code that is able to store a photo that is taken from the camera.
Take Photo code
#IBAction func takePhoto(_ sender: Any) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerController.SourceType.camera
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
takenPhoto.contentMode = .scaleToFill
takenPhoto.image = pickedImage
print(takenPhoto.image = pickedImage)
}
picker.dismiss(animated: true, completion: nil)
}
AWS S3 Bucket Code
#IBAction func uploadFile(_ sender: Any) {
uploadFile(with: "eartj", type: ".jpeg")
}
func uploadFile(with resource: String, type: String){
let key = "\(resource),\(type)"
let imagePath = Bundle.main.path(forResource: resource, ofType: type)!
let imageUrl = URL(fileURLWithPath: imagePath)
let request = AWSS3TransferManagerUploadRequest()!
request.bucket = "wuuurktest"
request.key = key
request.body = imageUrl
request.acl = .publicReadWrite
let transferManager = AWSS3TransferManager.default()
transferManager.upload(request).continueWith(executor: AWSExecutor.mainThread()) { (task) -> Any? in
if let error = task.error {
print(error)
}
if task.result != nil {
print("Uploaded File")
}
return nil
}
}
Link to the guide I am using to create the file upload
https://www.youtube.com/watch?v=UMgApUhg7ic
Most of the answers are outdated and too complicated. I was struggling with the same problem and finally found a solution.
This works best for me and works on Swift 5.
First of all, let's update the function to upload images to AWS.
func uploadToS3(url: URL) {
let fileArr = url.path.components(separatedBy: "/") // Path will be too long, so you have to separate the elements by / and store in an array
let key = fileArr.last // We get the last element of the array which in our case will be the image (my-image.jpg)
let localImageUrl = url
let request = AWSS3TransferManagerUploadRequest()!
request.bucket = bucketName
request.key = key
request.body = localImageUrl
request.acl = .publicReadWrite
let transferManager = AWSS3TransferManager.default()
transferManager.upload(request).continueWith(executor: AWSExecutor.mainThread()) { (task) -> Any? in
if let error = task.error {
print(error)
}
if task.result != nil {
print("Uploaded \(key)")
let contentUrl = self.s3Url.appendingPathComponent(bucketName).appendingPathComponent(key!)
self.contentUrl = contentUrl
}
return nil
}
}
In this block of code:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
takenPhoto.contentMode = .scaleToFill
takenPhoto.image = pickedImage
print(takenPhoto.image = pickedImage)
// Add here:
let url = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
.appendingPathComponent("my-image", isDirectory: false)
.appendingPathExtension("jpg") /* here we are naming the image 'my-image' and it will be 'jpg', if you want you can add a counter to increase the number each time you upload an image, and you make something like this: "my-image-\(counter)"*/
// Then write to disk
if let data = pickedImage.jpegData(compressionQuality: 0.8) {
do {
try data.write(to: url)
uploadToS3(url: url) //Call the updated function to store to AWS bucket
} catch {
print("Handle the error, i.e. disk can be full")
}
}
}
picker.dismiss(animated: true, completion: nil)
}
With this implementation, the image will be uploaded immediately to the server once you select the image from the library.
First thing you need to do is to store the picked image in your app's document directory as a temporary file. As soon as your image is picked, save it to the document directory using the below function.
func saveFileToDocumentDirectory(file: Data, fileExtension: String, folderName: String) -> URL? {
let formatter = DateFormatter()
formatter.dateFormat = "yyyyMMdd_HHmmss"
let stringOfDateTimeStamp = formatter.string(from: Date())
print("Date time stamp String: \(stringOfDateTimeStamp)")
let directoryPath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("\(folderName)/")
if !FileManager.default.fileExists(atPath: directoryPath) {
do {
try FileManager.default.createDirectory(at: NSURL.fileURL(withPath: directoryPath), withIntermediateDirectories: true, attributes: nil)
} catch {
print(error)
}
}
let filename = "/\(stringOfDateTimeStamp)_\(fileExtension)"
let customPath = "\(folderName)\(filename)"
let filepath = directoryPath+filename
print("FilePATH: \(filepath)")
let url = NSURL.fileURL(withPath: filepath)
do {
try file.write(to: url, options: .atomic)
print("CustomPAth:\(customPath)")
print(String.init("\(directoryPath)\(filename)"))
return url
} catch {
print(error)
print("file cant not be save at path \(filepath), with error : \(error)");
return nil
}
}
This will return a URL and you can then use the below function to upload that file to your S3 bucket.
func uploadToS3(url: URL, contentType: String, fileExtension: String){
SwiftLoader.show(title: "Uploading File", animated: true)
let accessKey = "YOUR_ACCESS_KEY"
let secretKey = "YOUR_SECRET_KEY"
let credentialsProvider = AWSStaticCredentialsProvider(accessKey: accessKey, secretKey: secretKey)
let configuration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
let remoteName = "IMG_\(UUID().uuidString)"+".\(fileExtension)"
let S3BucketName = "YOUR_BUCKET_NAME"
let uploadRequest = AWSS3TransferManagerUploadRequest()!
uploadRequest.body = url
uploadRequest.key = remoteName
uploadRequest.bucket = S3BucketName
uploadRequest.contentType = contentType
uploadRequest.acl = .publicRead
let transferManager = AWSS3TransferManager.default()
transferManager.upload(uploadRequest).continueWith(block: { (task: AWSTask) -> Any? in
if let error = task.error {
print("Upload failed with error: (\(error.localizedDescription))")
DispatchQueue.main.async {
print("An error occurred while Uploading your file, try again.")
SwiftLoader.hide()
}
}
if task.result != nil {
let url = AWSS3.default().configuration.endpoint.url
let publicURL = url?.appendingPathComponent(uploadRequest.bucket!).appendingPathComponent(uploadRequest.key!)
print("Uploaded to:\(String(describing: publicURL))")
}
return nil
})
}
Don't forget to delete your temporary file once your upload is successful.
Here is an example using TransferUtility:-
import AWSCognitoIdentityProvider
import AWSS3
typealias progressBlock = (_ progress: Double) -> Void
typealias completionBlock = (_ response: Any?, _ error: Error?) -> Void
//using Utility upload expression
func uploadImage(with image: URL, key: String?, progress: progressBlock?, completion: completionBlock?) {
let expression = AWSS3TransferUtilityUploadExpression()
expression.progressBlock = { (task: AWSS3TransferUtilityTask, awsProgress: Progress) -> Void in
//print(awsProgress.fractionCompleted)
guard let uploadProgress = progress else { return }
DispatchQueue.main.async {
uploadProgress(awsProgress.fractionCompleted)
}
}
expression.setValue("public-read-write", forRequestHeader: "x-amz-acl")
expression.setValue("public-read-write", forRequestParameter: "x-amz-acl")
// Completion block
var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
completionHandler = { (task, error) -> Void in
DispatchQueue.main.async(execute: {
if error == nil {
let url = AWSS3.default().configuration.endpoint.url
let publicURL = url?.appendingPathComponent(AWS.bucketName).appendingPathComponent(key!)
print("Uploaded to:\(String(describing: publicURL))")
if let completionBlock = completion {
completionBlock(publicURL?.absoluteString, nil)
}
} else {
if let completionBlock = completion {
completionBlock(nil, error)
}
}
})
}
// Start uploading using AWSS3TransferUtility
let awsTransferUtility = AWSS3TransferUtility.default()
awsTransferUtility.uploadFile(
image as URL,
bucket: AWS.bucketName, //Make sure you write the correct bucket name here
key: key!, //"private/{user_identity_id}/my-picture.png"
contentType: "image/png",
expression: expression,
completionHandler: completionHandler).continueWith(block: { (task) -> Any? in
if let error = task.error {
print("error is: \(error.localizedDescription)")
}
if let _ = task.result {
// your uploadTask
print("Starting upload...")
}
return nil
})
}
Two parameters I am passing:-
image: URL and key: String?
Here is how I get image and image name (key):-
//setting temp name for upload // I am using a random string here
let imageName = "\(CommonMethod.randomString(length: 6))" + ".png"
//settings temp location for image
let tempDirectoryUrl = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(imageName)
guard let localUrlPath = image!.save(at: tempDirectoryUrl) else { return }
//URL
print(localUrlPath)
Happy coding!
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.
I have done static image upload to AWS server successfully. When i combine it with imagepicker, I am facing a wierd issue due to which same image is being uploaded to AWS even though I pick and name them differently. The code is as follows:
internal func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [String : Any])
{
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
var imageUrl = info[UIImagePickerControllerReferenceURL] as? NSURL
let imageName = imageUrl?.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let photoURL = NSURL(fileURLWithPath: documentDirectory)
let localPath = photoURL.appendingPathComponent(imageName!)
print("image name : \(imageName)")
if !FileManager.default.fileExists(atPath: localPath!.path) {
do {
try UIImageJPEGRepresentation(image, 1.0)?.write(to: localPath!)
print("file saved")
//let imageData = NSData(contentsOf: localPath!)
//let finalURL = localPath!
//this is in swift 2; above 2 lines are its equivalent in swift3. I think the problem lies here
//let imageData = NSData(contentsOfFile: localPath)!
//imageURL = NSURL(fileURLWithPath: localPath)
}catch {
print("error saving file")
}
}
else {
print("file already exists")
}
self.dismiss(animated: true, completion: nil)
let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: "identity pool id")
let configuration = AWSServiceConfiguration(region: .APSoutheast1, credentialsProvider: credentialProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
//these are the static values I used that worked perfectly fine with separate images
//let localFileName = "Alerts_bg"
//let ext = "png"
//let remoteName = localFileName + "." + ext
//let imageURL = Bundle.main.url(forResource: localFileName, withExtension: ext)!
let transferManager = AWSS3TransferManager.default()
let uploadRequest = AWSS3TransferManagerUploadRequest()!
uploadRequest.bucket = "bucket"
let imageAWSName = "ios_" + NSUUID().uuidString + ".jpg"
uploadRequest.key = imageAWSName
uploadRequest.body = localPath! as URL
uploadRequest.contentType = "image/jpg"
print("req123 : \(uploadRequest)")
uploadRequest.uploadProgress = { (bytesSent, totalBytesSent, totalBytesExpectedToSend) -> Void in
DispatchQueue.main.async(execute: {
//self.amountUploaded = totalBytesSent // To show the updating data status in label.
//self.fileSize = totalBytesExpectedToSend
print("progress : \(totalBytesSent)/\(totalBytesExpectedToSend)")
})
}
transferManager.upload(uploadRequest).continueWith(executor: AWSExecutor.mainThread(), block: { (task:AWSTask<AnyObject>) -> Any? in
if let error = task.error {
print("Upload failed with error: (\(error.localizedDescription))")
}
if task.result != nil {
let s3URL = URL(string: "https://s3-ap-southeast-1.amazonaws.com/bucket/\(imageAWSName)")!
print("Uploaded to:\(s3URL)")
}
return nil
})
dismiss(animated:true, completion: nil) //5
}
I have seen lot of blogs such as this and this but these are in earlier versions of swift and I am unable to convert it in Swift 3 and combine imagepicker with AWS properly.
Someone please help.
I found a solution to my problem:
let imageAWSName = "ios_" + NSUUID().uuidString + ".jpg"
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let photoURL = NSURL(fileURLWithPath: documentDirectory)
let localPath = photoURL.appendingPathComponent(imageAWSName)
if !FileManager.default.fileExists(atPath: localPath!.path) {
do {
try UIImageJPEGRepresentation(image, 1.0)?.write(to: localPath!)
print("file saved")
}catch {
print("error saving file")
}
}
else {
print("file already exists")
}
let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: “your identity pool id”)
let configuration = AWSServiceConfiguration(region: .APSoutheast1, credentialsProvider: credentialProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
let transferManager = AWSS3TransferManager.default()
let uploadRequest = AWSS3TransferManagerUploadRequest()!
let yourBucketName = “your bucket name”
uploadRequest.bucket = yourBucketName
uploadRequest.key = imageAWSName
uploadRequest.body = localPath! as URL
uploadRequest.contentType = "image/jpg"
uploadRequest.uploadProgress = { (bytesSent, totalBytesSent, totalBytesExpectedToSend) -> Void in
DispatchQueue.main.async(execute: {
//self.amountUploaded = totalBytesSent // To show the updating data status in label.
//self.fileSize = totalBytesExpectedToSend
print("progress : \(totalBytesSent)/\(totalBytesExpectedToSend)")
})
}
transferManager.upload(uploadRequest).continueWith(executor: AWSExecutor.mainThread(), block: { (task:AWSTask<AnyObject>) -> Any? in
if let error = task.error {
print("Upload failed with error: (\(error.localizedDescription))")
}
if task.result != nil {
let s3URL = URL(string: "https://s3-ap-southeast-1.amazonaws.com/\(yourBucketName)/\(imageAWSName)")!
print("Uploaded to:\(s3URL)")
}
return nil
})
self.picker.dismiss(animated: true, completion: nil)
Make sure the imageAWSName used in localPath is always different as I have done. That is the main thing otherwise AWS will save same image multiple times even though you pick different images from picker.
Hope it helps someone in future!
Actually, when you are doing this:
let photoURL = NSURL(fileURLWithPath: documentDirectory)
let localPath = photoURL.appendingPathComponent(imageName!)
you are creating localPath as URL.
So when you are doing:
let imageURL = NSURL(fileURLWithPath: localPath)
It's giving error, because localPath is URL not String.
Here you can directly using as:
let imageURL = localPath!
I'm trying to upload an image to a bucket. The connection is made, the upload apparently starts but does not progress. The permissions on the server I consider to be correct, because an android app is able to upload.
In my appdelegate I have this:
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: AWSRegionType.USEast1, identityPoolId: "us-east-1:XXXXXX-XXXX-XXXX-XXXX-XXXX”, unauthRoleArn: "arn:aws:iam::XXXXX:role/Cognito_mybucketUnauth_Role", authRoleArn: "arn:aws:iam::XXXXX:role/Cognito_mybucketAuth_Role", identityProviderManager: nil)
let configuration = AWSServiceConfiguration(region: AWSRegionType.USEast1, credentialsProvider: credentialsProvider)
AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration
And this to get the image and upload
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]){
//getting details of image
let uploadFileURL = info[UIImagePickerControllerReferenceURL] as! NSURL
let imageName = uploadFileURL.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first! as String
// getting local path
let localPath = (documentDirectory as NSString).stringByAppendingPathComponent(imageName!)
//getting actual image
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let data = UIImagePNGRepresentation(image)
data!.writeToFile(localPath, atomically: true)
let imageData = NSData(contentsOfFile: localPath)!
imageURL = NSURL(fileURLWithPath: localPath)
CampoImagem.image = image
picker.dismissViewControllerAnimated(true, completion: nil)
uploadImage()
}
func uploadImage(){
//defining bucket and upload file name
let S3BucketName: String = “mybucket"
let S3UploadKeyName: String = "profile/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)")
})
}*/
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.uploadFile(imageURL, 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;
}
}
Print: Upload Starting!
I suspect it's something when ID and permission to complete the upload with aws, but I think if it was the upload would not start, correct?
How can I solve this?
Please check this code you can also check by adding credentials in this demo project
https://github.com/awslabs/aws-sdk-ios-samples/blob/master/S3TransferUtility-Sample/Swift/S3BackgroundTransferSampleSwift/FirstViewController.swift
I'm trying to render an image in UIImageView using Swift. The source object is located in an AWS S3 bucket. I could not find any example code on Google. So I tried to translate the code given in this link [AWS S3 SDK v2 for iOS - Download an image file to UIImage from Obj-C to Swift, but failed. I'm a beginner in iOS.
let accessKey = "ACCESS_CODE";
let secretKey = "SECRET_KEY";
// let credentialsProvider = AWSStaticCredentialsProvider.credentialsWithAccessKey(accessKey, secretKey: secretKey)
// ^ Xcode says - credentialsWithAccessKey is deprecated, use initWithAccessKey
let credentialsProvider = AWSStaticCredentialsProvider.initWithAccessKey(accessKey, secretKey: secretKey)
// ^ Xcode says - AWSStaticCredentialsProvider.Type does not have a member named ‘initWithAccessKey’
I could be doing very many things wrong here, even silly mistakes. The best help would be to point to some example code.
Have you tried like this
var credentialsProvider: AWSStaticCredentialsProvider = AWSStaticCredentialsProvider.credentialsWithAccessKey("MY_ACCESS_KEY", secretKey: "MY_SECRET_KEY")
var configuration: AWSServiceConfiguration = AWSServiceConfiguration.configurationWithRegion(AWSRegionUSWest1, credentialsProvider: credentialsProvider)
AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration
var transferManager: AWSS3 = AWSS3(configuration: configuration)
var getImageRequest: AWSS3GetObjectRequest = AWSS3GetObjectRequest.new()
getImageRequest.bucket = "MY_BUCKET"
getImageRequest.key = "MY_KEY"
transferManager.getObject(getImageRequest).continueWithExecutor(BFExecutor.mainThreadExecutor(), withBlock: {(task: BFTask) -> id in if task.error {
NSLog("Error: %#", task.error)
}
else {
NSLog("Got image")
var data: NSData = task.result.body()
dispatch_async(dispatch_get_main_queue(), {
var image: UIImage = UIImage.imageWithData(data)
myImageView.image = image
})
I created a custom class to download image. It worked for me.
class AWSImageDownloader {
init(AccessKey accessKey:String, SecretKey secretKey:String, andRegion region:AWSRegionType = .USEast1) {
let credentialsProvider = AWSStaticCredentialsProvider(accessKey: accessKey, secretKey: secretKey)
guard let configuration = AWSServiceConfiguration(region: region, credentialsProvider: credentialsProvider) else {
debugPrint("Failed to configure")
return
}
AWSServiceManager.default().defaultServiceConfiguration = configuration
}
func downloadImage(Name imageName:String, fromBucket bucketName:String, onDownload successCallback:#escaping AWSImageDownloadSuccess, andOnError errorCallback:#escaping AWSImageDownloadError){
let transferManager = AWSS3.default()
let getImageRequest = AWSS3GetObjectRequest()
getImageRequest?.bucket = bucketName
getImageRequest?.key = imageName
transferManager.getObject(getImageRequest!).continueWith(executor: AWSExecutor.mainThread()) { (anandt) -> Void in
if anandt.error == nil {
if let imageData = anandt.result?.body as? Data, let image = UIImage(data: imageData) {
successCallback(image)
} else {
errorCallback("Download failed")
}
} else {
let error = "Error \(anandt.error?.localizedDescription ?? "unknown by dev")"
errorCallback(error)
}
}
}
}