Reputation: 783
I want to build the upload system that client can only upload the file once.
How to implement this in firebase?
Upvotes: 1
Views: 2162
Reputation: 15963
I interpret this question two ways:
You can do both entirely in Storage security rules:
// Don't allow overwrites
service firebase.storage {
match /b/{bucket}/o {
match /files/{fileName} {
// Allow an initial upload, or a metadata change
allow write: if resource == null
|| request.resource.md5Hash == resource.md5Hash;
}
}
}
// Hash files so you only have one file
service firebase.storage {
match /b/{bucket}/o {
match /files/{fileHash} {
// Allow initial upload only, ensure that the hashes match
allow write: if resource == null
&& request.resource.md5Hash == fileHash;
}
}
}
Upvotes: 3
Reputation: 8020
This is the way I would do it:
I would use Firebase Functions, Storage and Database.
There is several ways of doing this, and mine might not be the easiet but it should get you going.
Get the MD5 hash on the client.
Write the MD5 hash to your database to something like /requests/{md5Hash}
Your function has an onWrite()
event listener for that endpoint.
The function looks for that md5Hash in another endpoint that is completely locked down (no read or write access to the outside world) in an endpoint like /files/{md5Hash}
.
(below is written in 'free hand' so there might be some errors, but you get the idea)
module.exports = functions.database.ref('requests/{userId}/{md5Hash}')
.onWrite(event => {
//Only respond to new writes
if (!event.data.val() || event.data.previous.val()) {
return null
}
const {userId, md5Hash} = event.params;
ref.child('files').child(userId).once('value')
.then(snapshot => {
return snapshot.hasChild(md5Hash)
})
.then(exists => {
//If the md5Hash doesn't already exist
var obj = {};
if (!exists) {
obj['status'] = 'permitted'
//This will be the path for Storage
obj['path'] = `files/${userId}/${md5Hash}`
} else {
obj['status'] = 'denied'
}
return event.data.ref.update(status)
})
.catch(error => {
console.log(error);
})
})
While this is going on your could make your client listen to your /request/{md5Hash}
endpoint. In this endpoint you could have a status key that will represent the status of the operation. If the cloud function detects that the md5 hash already exists, it will write /requests/{md5Hash}/status = denied
, if it doesn't it will write /requests/{md5Hash}/status = permitted
.\
You could then create a path for your file in your cloud function that will comprise of different parameters, e.g. const path = ${userId}/${files}/${md5Hash}
and then write that path to /requests/{md5Hash}/path
= yourPath
.
Then upload your object to Firebase Storage with the path given by functions.
Upvotes: 0