AWS S3 Bucket
is a very popular library to upload files like image, video, audio, etc. We are going to use AWS iOS SDK
and we will create an AWSS3Manager
class, using this manager class, we will upload any files by writing just one line code. AWSS3Manager
class will make it super easy to upload any type of files. Let’s not wait anymore and start coding…We suppose you already have
AWS S3 Bucket
setup, Pool-Id
and bucket name
, we will need these informations.– Create a new project or you can use your existing project as well.
– Open a terminal and navigate to your project.
– Run a command: pod init -Open the Podfile and write: pod ‘AWSS3’
-Now open the terminal again and run the command: pod install
Now your project file will look like below.
S3BucketUpload.xcworkspace
file from onward.
Setup AWS Credentials
OpenAppDelegate.swift
file and make below changes.
import UIKit
import AWSS3 // 1
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
self.initializeS3() //2
return true
}
//3
func initializeS3() {
let poolId = "***** your poolId *****" // 3-1
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: .USWest1, identityPoolId: poolId)//3-2
let configuration = AWSServiceConfiguration(region: .USWest1, credentialsProvider: credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
}
1 import AWSS3 framework
2 Call this function to set AWS up credential
3-1 Enter your
pool Id
3-2 Change your region based on your AWS account region.
Creating AWSS3Manager class
Create a new swift file and name itAWSS3Manager
import Foundation
import UIKit
import AWSS3 //1
typealias progressBlock = (_ progress: Double) -> Void //2
typealias completionBlock = (_ response: Any?, _ error: Error?) -> Void //3
class AWSS3Manager {
static let shared = AWSS3Manager() // 4
private init () { }
let bucketName = "***** your bucket name *****" //5
// Upload image using UIImage object
func uploadImage(image: UIImage, progress: progressBlock?, completion: completionBlock?) {
guard let imageData = image.jpegData(compressionQuality: 1.0) else {
let error = NSError(domain:"", code:402, userInfo:[NSLocalizedDescriptionKey: "invalid image"])
completion?(nil, error)
return
}
let tmpPath = NSTemporaryDirectory() as String
let fileName: String = ProcessInfo.processInfo.globallyUniqueString + (".jpeg")
let filePath = tmpPath + "/" + fileName
let fileUrl = URL(fileURLWithPath: filePath)
do {
try imageData.write(to: fileUrl)
self.uploadfile(fileUrl: fileUrl, fileName: fileName, contenType: "image", progress: progress, completion: completion)
} catch {
let error = NSError(domain:"", code:402, userInfo:[NSLocalizedDescriptionKey: "invalid image"])
completion?(nil, error)
}
}
// Upload video from local path url
func uploadVideo(videoUrl: URL, progress: progressBlock?, completion: completionBlock?) {
let fileName = self.getUniqueFileName(fileUrl: videoUrl)
self.uploadfile(fileUrl: videoUrl, fileName: fileName, contenType: "video", progress: progress, completion: completion)
}
// Upload auido from local path url
func uploadAudio(audioUrl: URL, progress: progressBlock?, completion: completionBlock?) {
let fileName = self.getUniqueFileName(fileUrl: audioUrl)
self.uploadfile(fileUrl: audioUrl, fileName: fileName, contenType: "audio", progress: progress, completion: completion)
}
// Upload files like Text, Zip, etc from local path url
func uploadOtherFile(fileUrl: URL, conentType: String, progress: progressBlock?, completion: completionBlock?) {
let fileName = self.getUniqueFileName(fileUrl: fileUrl)
self.uploadfile(fileUrl: fileUrl, fileName: fileName, contenType: conentType, progress: progress, completion: completion)
}
// Get unique file name
func getUniqueFileName(fileUrl: URL) -> String {
let strExt: String = "." + (URL(fileURLWithPath: fileUrl.absoluteString).pathExtension)
return (ProcessInfo.processInfo.globallyUniqueString + (strExt))
}
//MARK:- AWS file upload
// fileUrl : file local path url
// fileName : name of file, like "myimage.jpeg" "video.mov"
// contenType: file MIME type
// progress: file upload progress, value from 0 to 1, 1 for 100% complete
// completion: completion block when uplaoding is finish, you will get S3 url of upload file here
private func uploadfile(fileUrl: URL, fileName: String, contenType: String, progress: progressBlock?, completion: completionBlock?) {
// Upload progress block
let expression = AWSS3TransferUtilityUploadExpression()
expression.progressBlock = {(task, awsProgress) in
guard let uploadProgress = progress else { return }
DispatchQueue.main.async {
uploadProgress(awsProgress.fractionCompleted)
}
}
// 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(self.bucketName).appendingPathComponent(fileName)
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(fileUrl, bucket: bucketName, key: fileName, contentType: contenType, expression: expression, completionHandler: completionHandler).continueWith { (task) -> Any? in
if let error = task.error {
print("error is: \(error.localizedDescription)")
}
if let _ = task.result {
// your uploadTask
}
return nil
}
}
}
1 import AWSS3 framework
2 This is progress block which tells us how much data has been uploaded
3 This is the completion block which executes when uploading finish
4 Create a
shared instance
of this class5 Enter your
bucket name
here
Move to ViewController class
Open the nib file and add controls as shown in the below image – Create anIBOutlet
of UIProgressView
and uploaded file URL UILabel
.– Add
IBActions
on all four buttons.The code will look like below
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var s3UrlLabel: UILabel!
@IBOutlet weak var progressView: UIProgressView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.progressView.progress = Float(0.0)
}
@IBAction func tapUploadImage(_ sender: Any) {
}
@IBAction func tapUploadVideo(_ sender: Any) {
}
@IBAction func tapUploadAudio(_ sender: Any) {
}
@IBAction func tapUploadFile(_ sender: Any) {
}
}
Upload Image
We are going to use below function ofAWSS3Manager
class.
func uploadImage(image: UIImage, progress: progressBlock?, completion: completionBlock?)
Add below code in your tapUploadImage
function which is inside your UIViewController
class
@IBAction func tapUploadImage(_ sender: Any) {
guard let image = UIImage(named: "your-image") else { return } //1
AWSS3Manager.shared.uploadImage(image: image, progress: {[weak self] ( uploadProgress) in
guard let strongSelf = self else { return }
strongSelf.progressView.progress = Float(uploadProgress)//2
}) {[weak self] (uploadedFileUrl, error) in
guard let strongSelf = self else { return }
if let finalPath = uploadedFileUrl as? String { // 3
strongSelf.s3UrlLabel.text = "Uploaded file url: " + finalPath
} else {
print("\(String(describing: error?.localizedDescription))") // 4
}
}
}
1 Get your image2 Update the progress bar
3 In the completion block, you will get the uploaded image URL string
Upload Video
Below function is define underAWSS3Manager
class to upload video, we are going to use this
// Upload video from local path url
func uploadVideo(videoUrl: URL, progress: progressBlock?, completion: completionBlock?)
Add below code in your tapUploadVideo
function
@IBAction func tapUploadVideo(_ sender: Any) {
//guard let path = Bundle.main.path(forResource: "Video", ofType: "mov") else { return }
let videoUrl = URL(fileURLWithPath: "your video file path")
AWSS3Manager.shared.uploadVideo(videoUrl: videoUrl, progress: { [weak self] (progress) in
guard let strongSelf = self else { return }
strongSelf.progressView.progress = Float(progress)
}) { [weak self] (uploadedFileUrl, error) in
guard let strongSelf = self else { return }
if let finalPath = uploadedFileUrl as? String {
strongSelf.s3UrlLabel.text = "Uploaded file url: " + finalPath
} else {
print("\(String(describing: error?.localizedDescription))")
}
}
}
Now run the code and upload a video.
Upload Audio
To upload audio we will use the below function of AWSS3Manager// Upload auido from local path url
func uploadAudio(audioUrl: URL, progress: progressBlock?, completion: completionBlock?)
Add below code in your tapUploadAudio
function
@IBAction func tapUploadAudio(_ sender: Any) {
let audioUrl = URL(fileURLWithPath: "your audio local file path")
AWSS3Manager.shared.uploadAudio(audioUrl: audioUrl, progress: { [weak self] (progress) in
guard let strongSelf = self else { return }
strongSelf.progressView.progress = Float(progress)
}) { [weak self] (uploadedFileUrl, error) in
guard let strongSelf = self else { return }
if let finalPath = uploadedFileUrl as? String {
strongSelf.s3UrlLabel.text = "Uploaded file url: " + finalPath
} else {
print("\(String(describing: error?.localizedDescription))")
}
}
}
Upload other files like plain text, zip, etc
To upload other files, we will use the below function ofAWSS3Manager
class
// Upload files like Text, Zip, etc from local path url
func uploadOtherFile(fileUrl: URL, conentType: String, progress: progressBlock?, completion: completionBlock?)
Add below code in your tapUploadAudio
function
@IBAction func tapUploadAudio(_ sender: Any) {
let audioUrl = URL(fileURLWithPath: "your audio local file path")
AWSS3Manager.shared.uploadAudio(audioUrl: audioUrl, progress: { [weak self] (progress) in
guard let strongSelf = self else { return }
strongSelf.progressView.progress = Float(progress)
}) { [weak self] (uploadedFileUrl, error) in
guard let strongSelf = self else { return }
if let finalPath = uploadedFileUrl as? String {
strongSelf.s3UrlLabel.text = "Uploaded file url: " + finalPath
} else {
print("\(String(describing: error?.localizedDescription))")
}
}
}
Read our next article: UIDatePicker as inputView to UITextField in just one line
Do you have a tutorial that I can follow that will help with setting up the S3 portion of so that the proper permissions and setup will allow this to work?
Value of type ‘AWSS3TransferUtilityUploadExpression’ has no member ‘progressBlock’
Create object of AWSS3TransferUtilityProgressBlock and then use.
For ex : let progressBlock: AWSS3TransferUtilityProgressBlock?
progressBlock = {(task, progress) in
DispatchQueue.main.async {
print(“Progress: \(Float(progress.fractionCompleted))”)
}
}
expression.progressBlock = progressBlock
Create object of UploadExpression.
for ex :
progressBlock = {(task, progress) in
DispatchQueue.main.async {
print(“Progress: \(Float(progress.fractionCompleted))”)
}
}
expression.progressBlock = progressBlock
His,
Image is Zoomed and comprised.How can I upload direct image?
I upload audio but the response can’t get uploaded audio URL can you please help me how to get this URL