FirebaseStorage: как удалить каталог
FirebaseStorage всегда возвращает ошибку 400
при попытке удалить каталог, то есть что-то вроде следующего всегда возвращает ошибку 400
.
let storageRef = FIRStorage.storage().reference().child("path/to/directory")
storageRef.deleteWithCompletion { (error) in
print("error: \(error)") // always prints error code 400
}
Однако удаление файла работает нормально, например. что-то вроде не возвращает ошибку:
let storageRef = FIRStorage.storage().reference().child("path/to/file.jpg")
storageRef.deleteWithCompletion { (error) in
print("error: \(error)") // works fine, error is nil
}
Что я могу делать неправильно? Я не считаю, что это не поддерживается FirebaseStorage, потому что удаление файлов из каталога один за другим было бы довольно хромым (особенно, если указанный каталог имеет 100 или 1000 таких).
Ответы
Ответ 1
из группы google, удаление каталога невозможно. Вы должны хранить список файлов где-нибудь (в базе данных Firebase) и удалять их по одному.
https://groups.google.com/forum/#!topic/firebase-talk/aG7GSR7kVtw
Я также отправил запрос функции, но поскольку их трекер ошибок не является общедоступным, нет ссылки, которую я мог бы предоставить.
Ответ 2
Из контекста безопасной облачной функции Google - вы можете удалить весь каталог, используя пакет npm Google Cloud Storage (также известный как Google Cloud Storage API), например так:
const gcs = require('@google-cloud/storage')();
const functions = require('firebase-functions');
...
const bucket = gcs.bucket(functions.config().firebase.storageBucket);
return bucket.deleteFiles({
prefix: 'users/${userId}/'
}, function(err) {
if (err) {
console.log(err);
} else {
console.log('All the Firebase Storage files in users/${userId}/ have been deleted');
}
});
больше документации доступно на GCS API документах
Ответ 3
В 26/5/2017 нет способа удалить каталог. Но вы можете использовать мой алгоритм
Используйте этот код.
this.sliders = this.db.list(`users/${this.USER_UID}/website/sliders`) as FirebaseListObservable<Slider[]>
/**
* Delete image from firebase storage is take a string path of the image
* @param _image_path
*/
deleteImage(_image_path: string) {
// first delete the image
const storageRef = firebase.storage().ref();
const imageRef = storageRef.child(_image_path);
imageRef.delete().then(function() {
console.log('file deleted');
// File deleted successfully
}).catch(function(error) {
// Uh-oh, an error occurred!
console.log(error);
});
}
/**
* Deletes multiple Sliders, it takes an array of ids
* @param ids
*/
deleteMutipleSliders(ids: any) {
ids.forEach(id => {
this.getSliderDetails(id).subscribe(slider => {
let id = slider.$key; // i think this is not nesesery
const imgPath = slider.path;
this.deleteImage(imgPath);
});
return this.sliders.remove(id);
});
}
Ответ 4
Как указано выше, удаление каталога недопустимо. Я использую пример запроса списка файлов в базе данных Firebase и их удаления один за другим. Это мой запрос и вызов.
let messagePhotoQuery = messagesRef.child(group.key).child("messages").queryOrdered(byChild: "photoURL")
deleteMessagePhotos(from: messagePhotoQuery)
Это моя функция, проходящая через URL-адрес, а затем удаление файла по этой ссылке на хранилище.
func deleteMessagePhotos(from photoQuery: FIRDatabaseQuery) {
photoQuery.observeSingleEvent(of: .value, with: { (messagesSnapshot) in
guard messagesSnapshot.exists() else { return }
print(messagesSnapshot)
for message in messagesSnapshot.children {
let messageSnapshot = message as! FIRDataSnapshot
let messageData = messageSnapshot.value as! [String: AnyObject]
if let photoURL = messageData["photoURL"] as? String {
let photoStorageRef = FIRStorage.storage().reference(forURL: photoURL)
photoStorageRef.delete(completion: { (error) in
if let error = error {
print(error)
} else {
// success
print("deleted \(photoURL)")
}
})
}
}
})
}
Ответ 5
Вот одно из решений для удаления файлов в папке в Firebase Storage с использованием функций Firebase.
Предполагается, что у вас есть модели, хранящиеся в /MyStorageFilesInDatabaseTrackedHere/path1/path2 в вашей базе данных Firebase.
Эти модели будут иметь поле с именем "filename", которое будет иметь имя файла в Firebase Storage.
Рабочий процесс:
- Удалите папку в базе данных Firebase, которая содержит список моделей
- Прослушайте удаление этой папки с помощью функций Firebase
- Эта функция зацикливает дочерние элементы папки, получает имя файла и удаляет его в хранилище.
(Отказ от ответственности: папка в Хранилище остается в конце этой функции, поэтому для ее удаления необходимо выполнить еще один вызов.)
// 1. Define your Firebase Function to listen for deletions on your path
exports.myFilesDeleted = functions.database
.ref('/MyStorageFilesInDatabaseTrackedHere/{dbpath1}/{dbpath2}')
.onDelete((change, context) => {
// 2. Create an empty array that you will populate with promises later
var allPromises = [];
// 3. Define the root path to the folder containing files
// You will append the file name later
var photoPathInStorageRoot = '/MyStorageTopLevelFolder/' + context.params.dbpath1 + "/" + context.params.dbpath2;
// 4. Get a reference to your Firebase Storage bucket
var fbBucket = admin.storage().bucket();
// 5. "change" is the snapshot containing all the changed data from your
// Firebase Database folder containing your models. Each child has a model
// containing your file filename
if (change.hasChildren()) {
change.forEach(snapshot => {
// 6. Get the filename from the model and
// form the fully qualified path to your file in Storage
var filenameInStorage = photoPathInStorageRoot + "/" + snapshot.val().filename;
// 7. Create reference to that file in the bucket
var fbBucketPath = fbBucket.file(filenameInStorage);
// 8. Create a promise to delete the file and add it to the array
allPromises.push(fbBucketPath.delete());
});
}
// 9. Resolve all the promises (i.e. delete all the files in Storage)
return Promise.all(allPromises);
});
Ответ 6
Кажется, что единственный способ удалить каталог - это просмотреть все файлы и удалить их один за другим:
async function DeleteFirebaseStorageFolder(directoryName: string) {
const serviceAccount = require('../secret/adminSdkPrivateKey.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
storageBucket: 'gs://yourprojectname.appspot.com'
});
const bucket = admin.storage().bucket();
const files = (await bucket.getFiles({ directory: folderName }))[0];
const Deletions = [];
files.forEach(file => {
Deletions.push(bucket.file(file.name).delete());
})
await Promise.all(Deletions);
bucket.getFiles({ directory: folderName }).then((files) => {
console.log('Remaining number of files: ' + (files[0].length).toString());
})
}
DeleteFirebaseStorageFolder('myDirectoryName');
Ответ 7
По состоянию на июль 2019 года вы можете перечислить папку и рекурсивно удалить ее содержимое:
deleteFolderContents(path) {
let ref = firebase.storage().ref(path);
ref.listAll()
.then(dir => {
dir.items.forEach(fileRef => {
this.deleteFile(ref.fullPath, fileRef.name);
});
dir.prefixes.forEach(folderRef => {
this.deleteFolderContents(folderRef.fullPath);
})
})
.catch(error => {
console.log(error);
});
}