问题
Here's a brief overview of the process that I need help with:
Client uploads images to Firebase Storage at users/displayName/uid/ - this step is clear and done. No help needed on this one.
Then, client presses "request a quote" button which saves the URLs of the images (the ones that were uploaded to Storage in step 1) to Firebase Firestore - this step is clear and done. No help needed on this one.
After the URLs are saved to the Firestore, I want those images from Step 1 to be moved within the same bucket of the Storage to users/displayName/uid/order1. So, basically, from users/displayName/uid/ to users/displayName/uid/order1. - I need help with writing out the right Javascript code for this action. I tried the code snippet from below but it does not seem to work, not sure what is wrong.
At some point in the future, the same client will need to upload more images thus repeating the first 3 steps above. However, on the 3rd step, I will need his images to be moved from users/displayName/uid/ to users/displayName/uid/order2. The problem lies in me not knowing how to render the last part of the directory as order2 and not the same order1 as in the 3rd step. The number after "order" will basically need to increase every time the client repeats the steps. I have no idea of how to write out the right code for this. Please help.
If it helps, here are my functions that upload images to Firebase Storage and Firebase Firestore:
// Upload to Storage
handleUpload = () => {
this.state.files.forEach((file) => {
const storageRef = firebase.storage().ref(`users/${this.state.displayName}/${this.state.uid}/${file.name}`);
var task = storageRef.put(file)
// Progress
task.on("state_changed", snapshot => {
const progress = Math.round(
(snapshot.bytesTransferred / snapshot.totalBytes) * 100
);
this.setState({ progress });
},
// Error
error => {
console.log(error);
},
// Additional function to update state with all files uploaded
() => {
firebase.storage()
.ref(`users/${this.state.displayName}/${this.state.uid}`)
.child(file.name)
.getDownloadURL()
.then(url => {
this.setState(state => {
const urls = [...state.urls, url];
return {
urls
};
});
});
// Empty file upload
this.setState({ progress: 0 })
this.setState({ files: [] })
}
);
})
};
// Saving to Firestore - PRESS GET A QUOTE TO ACTIVATE
async saveToFirestore() {
// Getting it all from storage first
const listRef = firebase.storage().ref(`users/${this.state.displayName}/${this.state.uid}`)
const res = await listRef.listAll()
const urlPromises = res.items.map((itemRef) => {
return itemRef.getDownloadURL()
})
const urls = await Promise.all(urlPromises)
// Then, we save it all to Firestore
firebase.firestore().collection('Documents/').doc(this.state.displayName).set({
documents: urls,
quote: 'pending',
name: this.state.displayName,
email: this.state.email,
emailVerified: this.state.emailVerified,
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
userId: this.state.uid
})
.then(() => {
const listRef = firebase.storage().ref(`users/${this.state.displayName}/${this.state.uid}`)
listRef.listAll().then((res) => {
console.log(res)
res.items.forEach(function (item) {
console.log(item)
firebase.storage().ref(`users/${this.state.displayName}/${this.state.uid}/order1/${item.name}`).put(item);
});
}).catch(function (error) {
// Uh-oh, an error occurred!
});
this.setState({ quote: "pending" })
firebase.firestore().collection('Documents/').doc(this.state.displayName).get().then((doc) => {
if (doc.exists) {
doc.data().documents.forEach(url => {
this.setState(state => {
const documents = [...state.documents, url];
return {
documents
};
});
})
this.setState({ createdAt: doc.data().createdAt.toDate().toString() })
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
}).catch(function (error) {
console.log("Error getting document:", error);
});
})
.catch((error) => {
console.error("Error writing document: ", error);
});
}
Please let me know if anything else is needed.
Thank you very much!
回答1:
As far as I can tell, you have two parts to your question:
- Determine the folder for the next order
- Write all files from the root to this folder
I'll focus on the first step in this answer.
Determine the folder for the next order
To determine the next order?
folder, we'll get a list of all files/folders from Storage, and then filter them to determine the highest number in there:
var ref = firebase.storage().ref("62849565");
ref.listAll().then(function(res) {
// Determine the next order folder
const orderFolders = res.prefixes.filter((folder) => folder.name.match(/^order(\d+)$/));
let highestOrderNumber = 0;
orderFolders.forEach((folder) => {
const match = folder.name.match(/^order(\d+)$/);
const number = parseInt(match[1]);
if (number > highestOrderNumber) {
highestOrderNumber = number;
}
})
const nextOrderFolderPrefix = "order" + (highestOrderNumber+1);
// Move the files from the root to the new folder
res.items.forEach(function(itemRef) {
// TODO: read file from root and write it to the next order folder
});
}).catch(function(error) {
console.error(error);
});
(Also see this jsbin where I created/tested this code)
In the above:
- The
res.prefixes.filter((folder) => folder.name.match(/^order(\d+)$/))
ensures we only consider folders following theorder1
naming pattern. - We then loop over the folders to find the highest number.
- We them determine the path for the next folder.
Write all files from the root to the new folder
The TODO
in this code is to move the actual file. There is no operation in Cloud Storage (or its Firebase SDK) to move a file. So you will have to do a sequence of read the file, write it to its new location, and removing it from its original location. I recommend searching around a bit, as I'm pretty sure this must have been asked before.
来源:https://stackoverflow.com/questions/62849565/how-do-i-dynamically-create-a-firebase-storage-reference-based-on-previous-refer