Buscar..
Suba una imagen o un video a S3 usando AWS SDK
Antes de comenzar con el ejemplo, recomendaría crear un Singleton con un miembro de la clase delegado para poder utilizar un archivo en segundo plano y dejar que el usuario siga usando su aplicación mientras los archivos se cargan, incluso cuando la aplicación es el fondo
Comencemos, primero, debemos crear una enumeración que represente la configuración de S3:
enum S3Configuration : String
{
case IDENTITY_POOL_ID = "YourIdentityPoolId"
case BUCKET_NAME = "YourBucketName"
case CALLBACK_KEY = "YourCustomStringForCallBackWhenUploadingInTheBackground"
case CONTENT_TYPE_IMAGE = "image/png"
case CONTENT_TYPE_VIDEO = "video/mp4"
}
Ahora, deberíamos establecer las credenciales cuando su aplicación se inicie por primera vez, por lo tanto, debemos configurarlas dentro de AppDelegate
en el método didFinishLaunchingWithOptions
(preste atención a que debe establecer su región en el regionType
):
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
let credentialProvider = AWSCognitoCredentialsProvider(regionType: .EUWest1, identityPoolId: S3Configuration.IDENTITY_POOL_ID.rawValue)
let configuration = AWSServiceConfiguration(region: .EUWest1, credentialsProvider: credentialProvider)
AWSS3TransferUtility.registerS3TransferUtilityWithConfiguration(configuration, forKey: S3Configuration.CALLBACK_KEY.rawValue)
}
Como ya estamos dentro de AppDelegate, deberíamos implementar la devolución de llamada en segundo plano que maneja el SDK de AWS:
func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void)
{
// Will print the identifer you have set at the enum: .CALLBACK_KEY
print("Identifier: " + identifier)
// Stores the completion handler.
AWSS3TransferUtility.interceptApplication(application,
handleEventsForBackgroundURLSession: identifier,
completionHandler: completionHandler)
}
Ahora, cuando el usuario mueva la aplicación al fondo, su carga continuará con la carga real.
Para cargar el archivo con el SDK de AWS, tendremos que escribir el archivo en el dispositivo y darle a la SDK la ruta real. Por el bien del ejemplo, imagine que tenemos un UIImage (también podría ser un video ...) y lo escribiremos en una carpeta temporal:
// Some image....
let image = UIImage()
let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(fileName)
let filePath = fileURL.path!
let imageData = UIImageJPEGRepresentation(image, 1.0)
imageData!.writeToFile(filePath, atomically: true)
FileURL y fileName se utilizarán para la carga real más adelante.
Hay 2 cierres que tendremos que definir que son proporcionados por el SDK de AWS,
-
AWSS3TransferUtilityUploadCompletionHandlerBlock
: un cierre que notifica cuando se realiza la carga (o no) -
AWSS3TransferUtilityUploadProgressBlock
: un cierre que notifica cada byte enviado
Si planea tener un Singleton debe definir esos tipos como miembros de la clase. La implementación debería verse así:
var completionHandler : AWSS3TransferUtilityUploadCompletionHandlerBlock? =
{ (task, error) -> Void in
if ((error) != nil)
{
print("Upload failed")
}
else
{
print("File uploaded successfully")
}
}
var progressBlock : AWSS3TransferUtilityUploadProgressBlock? =
{ [unowned self] (task, bytesSent:Int64, totalBytesSent:Int64, totalBytesExpectedToSend:Int64) -> Void in
let progressInPercentage = Float(Double(totalBytesSent) / Double(totalBytesExpectedToSend)) * 100
print(progressInPercentage)
}
NOTA: Si está utilizando un Singleton, es posible que desee definir un delegado que informará sobre el progreso o cuando se complete el archivo. Si no está utilizando un Singleton, puede crear un método estático que tenga los tipos relevantes:
static func uploadImageToS3(fileURL : NSURL,
fileName : String,
progressFunctionUpdater : Float -> Void,
resultBlock : (NSError?) -> Void)
{
// Actual implementation .....
// ...
// ...
}
-
progressFunctionUpdater
: informará a una función con progreso. -
resultBlock
: si devuelve nil, la carga se realizó con éxito, envía el objeto de error
Señoras y señores, la carga real:
let fileData = NSData(contentsOfFile: fileURL.relativePath!)
let expression = AWSS3TransferUtilityUploadExpression()
expression.uploadProgress = progressBlock
let transferUtility = AWSS3TransferUtility.S3TransferUtilityForKey(S3Configuration.CALLBACK_KEY.rawValue)
transferUtility?.uploadData(fileData!,
bucket: S3Configuration.BUCKET_NAME.rawValue,
key: fileName,
contentType: S3Configuration.CONTENT_TYPE_IMAGE.rawData,
expression: expression,
completionHander: completionHandler).continueWithBlock
{ (task : AWSTask) -> AnyObject? in
if let error = task.error
{
print(error)
}
if let exception = task.exception
{
print("Exception: " + exception.description)
}
if let uploadTask = task.result as? AWSS3TransferUtilityUploadTask
{
print("Upload started...")
}
return nil
}
Feliz S3 subiendo :)