Ricerca…
Carica un'immagine o un video su S3 utilizzando AWS SDK
Prima di iniziare con l'esempio, consiglierei di creare un Singleton con un membro della classe delegato in modo da poter ottenere un caso di utilizzo del caricamento di un file in background e consentire all'utente di continuare a utilizzare l'app mentre i file vengono caricati anche quando l'app è lo sfondo.
Iniziamo, innanzitutto, dovremmo creare un enum che rappresenti la configurazione 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"
}
Ora, dovremmo impostare le credenziali quando la tua app didFinishLaunchingWithOptions
per la prima volta, quindi dovremmo impostarle all'interno di AppDelegate
nel metodo didFinishLaunchingWithOptions
(fai attenzione che dovresti impostare la tua regione sul parametro 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)
}
Poiché siamo già all'interno di AppDelegate, dovremmo implementare la richiamata in background gestita dall'SDK 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)
}
Ora, quando l'utente sposta l'app sullo sfondo, il caricamento continuerà il caricamento effettivo.
Per caricare il file utilizzando l'SDK AWS dovremo scrivere il file sul dispositivo e fornire all'SDK il percorso effettivo. Per fare un esempio, immagina di avere un UIImage (potrebbe anche essere un video ...) e lo scriveremo in una cartella temporanea:
// 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 e fileName verranno utilizzati per il caricamento effettivo in seguito.
Ci sono 2 chiusure che dovremo definire fornite dall'SDK di AWS,
-
AWSS3TransferUtilityUploadCompletionHandlerBlock
- Una chiusura che avvisa quando il caricamento è terminato (o meno) -
AWSS3TransferUtilityUploadProgressBlock
- Una chiusura che notifica ogni byte inviato
Se si prevede di avere un Singleton, è necessario definire tali tipi come membri della classe. L'implementazione dovrebbe assomigliare a questa:
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: Se si utilizza un Singleton, è possibile che si desideri definire un delegato che lo segnalerà all'avanzamento o al termine del file. Se non si utilizza un Singleton, è possibile creare un metodo statico con i tipi rilevanti:
static func uploadImageToS3(fileURL : NSURL,
fileName : String,
progressFunctionUpdater : Float -> Void,
resultBlock : (NSError?) -> Void)
{
// Actual implementation .....
// ...
// ...
}
-
progressFunctionUpdater
: riporterà a una funzione in corso. -
resultBlock
- Se si restituisce nil, il caricamento ha avuto esito positivo, si invia l'oggetto error
Signore e signori, il caricamento effettivo:
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
}
Caricamento S3 felice :)