J'essaie d'utiliser le compartiment AWS S3
pour stocker les photos des utilisateurs à partir de quand ils les ont prises sur leur téléphone. J'ai actuellement mon code configuré au point où l'utilisateur peut prendre une photo de quelque chose et l'afficher sur UIImageView
.
Le problème que je rencontre est que j'ai Je n'ai aucune idée de comment le stocker sur le compartiment S3, j'ai actuellement du code capable de stocker une photo spécifiée dans le compartiment, mais pas vraiment du code capable de stocker une photo prise depuis l'appareil photo.
Code de prise de photo@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 } }
Code de compartiment AWS S3
@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) }
Lien vers le guide que j'utilise pour créer le téléchargement du fichier
3 Réponses :
La première chose à faire est de stocker l'image sélectionnée dans le répertoire de documents de votre application en tant que fichier temporaire. Dès que votre image est sélectionnée, enregistrez-la dans le répertoire du document en utilisant la fonction ci-dessous.
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 }) }
Cela renverra une URL et vous pourrez ensuite utiliser la fonction ci-dessous pour télécharger ce fichier sur votre S3 bucket.
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 } }
N'oubliez pas de supprimer votre fichier temporaire une fois le téléversement réussi.
Existe-t-il un moyen de l'enregistrer sans l'enregistrer temporairement après avoir pris la photo avec l'appareil photo?
Il pourrait y en avoir, je ne peux pas vous dire avec certitude. Mais j'ai essayé beaucoup de méthodes différentes, et cela a parfaitement fonctionné pour moi. Dans mon cas, j'avais plusieurs types de fichiers tels que les fichiers audio, vidéo, images et documents. Donc, mon approche ici est plus généralisée. J'appelle cette même fonction pour télécharger n'importe quel type de fichier sur S3. D'après mes recherches, je pense qu'il est nécessaire de le stocker temporairement, car vous transmettez l'URL du fichier à S3 en tant que corps
.
Hé Zubair, utilisez juste ci-dessous l'extension UIImage que j'ai créée fonctionnera directement dans l'objet UIImage
extension UIImage { //MARK: Uploading image function with S3 server... //MARK: ========================================== func uploadImageToS3(uploadFolderName: String = "", compressionRatio : CGFloat = 1, success : @escaping (Bool, String) -> Void, progress : @escaping (CGFloat) -> Void, failure : @escaping (Error) -> Void) { let name = "\(Int(Date().timeIntervalSince1970)).jpeg" let path = NSTemporaryDirectory().stringByAppendingPathComponent(path: name) //MARK: Compressing image before making upload request... guard let data = UIImageJPEGRepresentation(self, compressionRatio) else { let err = NSError(domain: "Error while compressing the image.", code : 01, userInfo : nil) failure(err) return } //MARK: Making upload request after image compression is done... guard let uploadRequest = AWSS3TransferManagerUploadRequest() else { let err = NSError(domain: "There is a problem while making the uploading request.", code : 02, userInfo : nil) failure(err) return } uploadRequest.bucket = "\(S3Details.bucketName)/\(S3Details.BUCKET_DIRECTORY)\(uploadFolderName.isEmpty ? "" : "/\(uploadFolderName)")" uploadRequest.acl = AWSS3ObjectCannedACL.publicRead uploadRequest.key = name try? data.write(to: URL(fileURLWithPath : path), options : .atomic) uploadRequest.body = URL(fileURLWithPath: path) uploadRequest.uploadProgress = {( bytesSent : Int64, totalBytesSent : Int64, _ totalBytesExpectedToSend : Int64) -> Void in progress((CGFloat(totalBytesSent)/CGFloat(totalBytesExpectedToSend))) print((CGFloat(totalBytesSent)/CGFloat(totalBytesExpectedToSend))) } AWSS3TransferManager.default().upload(uploadRequest).continueWith(executor: AWSExecutor.default()) { (task) -> Void in //MARK: That will remove image from temporary storage (NSTemporaryDirectory())... try? FileManager.default.removeItem(atPath : path) if let err = task.error { failure(err) } else { let imageURL = "\(S3Details.s3Url)\(S3Details.bucketName)/\(S3Details.BUCKET_DIRECTORY)\(uploadFolderName.isEmpty ? "" : "/\(uploadFolderName)")/\(name)" // printDebug(imageURL) success(true, imageURL) } } } }
Hé Shivam, serait-il important que j'utilise une UIImageView?
vous pouvez obtenir une image à partir d'imageview en utilisant également imageview.image, donc oui, vous pouvez l'utiliser, mais dans pickerController, vous obtenez une utilisation d'image en téléchargement là-bas, je ne sais pas votre cas d'utilisation, mais vous pouvez également l'utiliser sur imageview, j'espère que cela aide :)
Il indique que 'AWSS3TransferManager' est obsolète: utilisez `AWSS3TransferUtility` pour les opérations de chargement et de téléchargement.
. Pouvez-vous mettre à jour cette réponse pour le dernier SDK S3?
Voici un exemple utilisant TransferUtility
:-
//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)
Deux paramètres que je passe: -
image: URL et
key: String?
Voici comment j'obtiens l'image et le nom de l'image (clé): -
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 }) }
Bon codage!