我只想使用swift在firebase上上传多个图像。我现在正在上传一张图片,但无法上传多张图片。这是我的代码
let photoIdString = NSUUID().uuidString let storageRef = Storage.storage().reference(forURL: Config.STORAGE_ROOF_REF).child("posts").child(photoIdString) storageRef.putData(imageData, metadata: nil,completion: {(metadata,error) in if error != nil { return } let photoUrl = metadata?.downloadURL()?.absoluteString let ref = Database.database().reference() let postReference = ref.child("posts") let newPostId = postReference.childByAutoId().key let newPostReference = postReference.child(newPostId) newPostReference.setValue(["photoUrl":photoUrl,"caption":self.textView.text!])
当前没有直接API可以批量上传/下载文件。我们不能使用循环,因为所有任务都执行asynchronously。我们可以做的是使用递归函数。
asynchronously
核心逻辑
let images = [image1, image2, image3, image4] func uploadImage(forIndex index: Int) { if index < images.count { /// Perform uploading /// After successfully uploading call this method again by increment the **index = index + 1** return; } /// All images have been uploaded successfully }
完整代码示例
1.我创建了一个自定义类来上传文件
import UIKit import Firebase class FirFile: NSObject { /// Singleton instance static let shared: FirFile = FirFile() /// Path let kFirFileStorageRef = Storage.storage().reference().child("Files") /// Current uploading task var currentUploadTask: StorageUploadTask? func upload(data: Data, withName fileName: String, block: @escaping (_ url: String?) -> Void) { // Create a reference to the file you want to upload let fileRef = kFirFileStorageRef.child(fileName) /// Start uploading upload(data: data, withName: fileName, atPath: fileRef) { (url) in block(url) } } func upload(data: Data, withName fileName: String, atPath path:StorageReference, block: @escaping (_ url: String?) -> Void) { // Upload the file to the path self.currentUploadTask = path.putData(data, metadata: nil) { (metaData, error) in let url = metaData?.downloadURL()?.absoluteString block(url) } } func cancel() { self.currentUploadTask?.cancel() } }
2.在这里我们如何使用
首先,为主要功能创建一个完成块,当您成功上传所有图像时,它将通知您。
/// This is your images array let images = [image1, image2, image3, image4] /// Here is the completion block typealias FileCompletionBlock = () -> Void var block: FileCompletionBlock?
以下是两个函数,第一个是第一个函数,它将开始上载,第二个是递归,如果有下一个图像可以上载,它将调用自己。
func startUploading(completion: @escaping FileCompletionBlock) { if images.count == 0 { completion() return; } block = completion uploadImage(forIndex: 0) } func uploadImage(forIndex index:Int) { if index < images.count { /// Perform uploading let data = UIImagePNGRepresentation(images[index])! let fileName = String(format: "%@.png", "yourUniqueFileName") FirFile.shared.upload(data: data, withName: fileName, block: { (url) in /// After successfully uploading call this method again by increment the **index = index + 1** print(url ?? "Couldn't not upload. You can either check the error or just skip this.") self.uploadImage(forIndex: index + 1) }) return; } if block != nil { block!() } }
最后是带有完成块的主要功能
startUploading { /// All the images have been uploaded successfully. }
编辑新Firebase的“上传”功能:
唯一的区别是下载URL的方式。这是相同的新Firebase文档。
func upload(data: Data, withName fileName: String, atPath path:StorageReference, block: @escaping (_ url: String?) -> Void) { // Upload the file to the path self.currentUploadTask = path.putData(data, metadata: nil) { (metaData, error) in guard let metadata = metadata else { // Uh-oh, an error occurred! block(nil) return } // Metadata contains file metadata such as size, content-type. // let size = metadata.size // You can also access to download URL after upload. path.downloadURL { (url, error) in guard let downloadURL = url else { // Uh-oh, an error occurred! block(nil) return } block(url) } } }