Home > Software engineering >  How to assign uploaded image to specific DocumentID?
How to assign uploaded image to specific DocumentID?

Time:10-12

I have a simple form with textfields and image picker, user can upload it to Firebase.

How to let @DocumentID = ... in Storage section? Purpose: I need the image to be saved as a link in one document. At the moment the image is saved only in Storage. How to do it correctly?

All attempts led me to the fact that pic is created as a separate document in the database, and not inside same document.

enter image description here

Button: Done -[AddItemView]

@ObservedObject var viewModel = NewItemView()

func handleDoneTapped() {
    self.viewModel.handleDoneTapped()
    self.uploadImage()
    self.dismiss()
}

Storage section -[AddItemView]

@ObservedObject var viewModel = NewItemView()

func uploadImage() {
    let storage = Storage.storage().reference()
    let picData: Data  = pickedImages[0].jpegData(compressionQuality: 0.5)!
//        let userId = Auth.auth().currentUser?.uid
    let path = "itemImages/\(UUID().uuidString).jpg"
    let ref = storage.child(path)
    let metadata = StorageMetadata()
    metadata.contentType = "image/jpg"
    let uploadTask = ref.putData(picData, metadata: metadata, completion: { (storageMetaData, error) in
            
        if error != nil {
                
            print(error?.localizedDescription as Any)
            return

        }
    })        
}

All vars -[SingleItem]

struct SingleItem: Identifiable, Codable {
    @DocumentID var id: String?   // How I can use it in Storage section?
    var title : String
    var author : String
    var description : String
    @ServerTimestamp var createdTime: Timestamp?
    var userId : String?
    var pic : String
}
  
enum CodingKeys: String, CodingKey {
    case id
    case title
    case author
    case description = ""
    case pic
}

Firestore -[NewItemView]

class NewItemView: ObservableObject {
    // MARK: - Public properties
  
    @Published var singleitem: SingleItem
    @Published var modified = false
  
    // MARK: - Internal properties
  
    private var cancellables = Set<AnyCancellable>()
  
    // MARK: - Constructors
  
    init(singleitem: SingleItem = SingleItem(title: "", author: "", description: "", pic: "")) {
        self.singleitem = singleitem
    
        self.$singleitem
            .dropFirst()
            .sink { [weak self] singleitem in
                self?.modified = true
            }
            .store(in: &self.cancellables)
    }
  
    // MARK: - Firestore
  
    private var db = Firestore.firestore()
  
    private func addItem(_ singleitem: SingleItem) {
        do {
            var addedItem = singleitem
            addedItem.userId = Auth.auth().currentUser?.uid
            _ = try db.collection("items").addDocument(from: addedItem)
        
        }
        catch {
            print(error)
        }      
      
    }

    private func updateItem(_ singleitem: SingleItem) {
        if let documentID = singleitem.id {
            do {
                try db.collection("items").document(documentID).setData(from: singleitem)
            }
            catch {
                print(error)
            }
        }
    }

    private func updateOrAddItem() {
        if singleitem.id != nil {
            self.updateItem(self.singleitem)
        }
        else {
            addItem(singleitem)
        }
    }

    func handleDoneTapped() {     // And this func I call in Done button
        self.updateOrAddItem()
    }
}

CodePudding user response:

You created your path in uploadImage. You just need to update your object with that path that you statically created.

// You make the path to the image here
let path = "itemImages/\(UUID().uuidString).jpg"

You can do this multiple ways, but you need something like

func uploadImage() {
    let storage = Storage.storage().reference()
    let picData: Data  = pickedImages[0].jpegData(compressionQuality: 0.5)!
    let path = "itemImages/\(UUID().uuidString).jpg"
    let ref = storage.child(path)
    let metadata = StorageMetadata()
    metadata.contentType = "image/jpg"
    let uploadTask = ref.putData(picData, metadata: metadata, completion: { (storageMetaData, error) in
        if error != nil {
            print(error?.localizedDescription as Any)
            return
        } else {
            // Upload succeeded with the path you added
            // So set the pic variable to the path
            self.viewModel.singleItem.pic = path
            // Then update the item
            self.viewModel.updateOrAddItem()
        }
    })        
}
  • Related