Как получить список всех файлов в облачном хранилище в приложении Firebase?


Я работаю над загрузкой изображений, все работает отлично, но у меня есть 100 фотографий и я хотел бы показать их все в моем View, поскольку я получаю полный список изображений в папке, я не могу найти API для этой работы.

12 59

12 ответов:

в настоящее время нет вызова API в хранилище Firebase для перечисления всех файлов в папке. Если вам нужна такая функциональность, вы должны хранить метаданные файлов (например, URL-адреса загрузки) в месте, где вы можете их перечислить. Элемент Опорному Пункту В Реальном Времени Базы Данных идеально подходит для этого и позволяет также легко обмениваться URL-адреса с другим.

вы можете найти хороший (но несколько вовлеченный) образец этого в нашем FriendlyPix примера приложения. Соответствующий код для веб-версии здесь, но есть также версии для iOS и Android.

Так как нет языка в списке, я отвечу на это в Swift. Мы настоятельно рекомендуем использовать огневую базу хранения и база данных военнослужащих в реальном времени для достижения списков закачек:

Shared:

// Firebase services
var database: FIRDatabase!
var storage: FIRStorage!
...
// Initialize Database, Auth, Storage
database = FIRDatabase.database()
storage = FIRStorage.storage()
...
// Initialize an array for your pictures
var picArray: [UIImage]()

загрузки:

let fileData = NSData() // get data...
let storageRef = storage.reference().child("myFiles/myFile")
storageRef.putData(fileData).observeStatus(.Success) { (snapshot) in
  // When the image has successfully uploaded, we get it's download URL
  let downloadURL = snapshot.metadata?.downloadURL()?.absoluteString
  // Write the download URL to the Realtime Database
  let dbRef = database.reference().child("myFiles/myFile")
  dbRef.setValue(downloadURL)
}

скачать:

let dbRef = database.reference().child("myFiles")
dbRef.observeEventType(.ChildAdded, withBlock: { (snapshot) in
  // Get download URL from snapshot
  let downloadURL = snapshot.value() as! String
  // Create a storage reference from the URL
  let storageRef = storage.referenceFromURL(downloadURL)
  // Download the data, assuming a max size of 1MB (you can change this as necessary)
  storageRef.dataWithMaxSize(1 * 1024 * 1024) { (data, error) -> Void in
    // Create a UIImage, add it to the array
    let pic = UIImage(data: data)
    picArray.append(pic)
  })
})

для получения дополнительной информации см. раздел ноль в приложение: разработка с Firebase, и связанный исходный код, для практического примера того, как это сделать.

С Марта 2017: С добавлением Функции Облака Firebase, и более глубокая интеграция Firebase с Google Cloud, теперь это возможно.

с облачными функциями вы можете использовать пакет Google Cloud Node, чтобы сделать эпос операции с облачным хранилищем. Ниже приведен пример, который получает все URL-адреса файлов в массив из облачного хранилища. Эта функция будет срабатывать каждый раз, когда что-то сохраняется в облачном хранилище google.

Примечание 1: это довольно дорогостоящая вычислительная операция, так как она должна циклически проходить через все файлы в корзине / папке.

примечание 2.: Я написал это просто в качестве примера, не обращая особого внимания на обещания и т. д. Просто чтобы дать представление.

const functions = require('firebase-functions');
const gcs = require('@google-cloud/storage')();

// on file upload to google cloud storage
exports.fileUploaded = functions.storage.object().onChange(event => {

  const object = event.data; // the object that was just uploaded
  const bucket = gcs.bucket(object.bucket);
  const signedUrlConfig = { action: 'read', expires: '03-17-2025' }; // this is a signed url configuration object

  var fileURLs = []; // array to hold all file urls 

  // just for example. ideally you should get this from the object that is uploaded for this to be a better function :)
  // so that you can calculate the size of the folder it's uploaded to, and do something with it etc.
  const folderPath = "a/path/you/want/its/folder/size/calculated";

  bucket.getFiles({ prefix: folderPath }, function(err, files) {
    // files = array of file objects
    // not the contents of these files, we're not downloading the files. 

    files.forEach(function(file) {
      file.getSignedUrl(signedUrlConfig, function(err, fileURL) {
        console.log(fileURL);
        fileURLs.push(fileURL);
      });
    });

  });

});

Я надеюсь, это даст вам общее представление. Для лучших примеров облачных функций, проверьте РЕПО GitHub Google, полное образцов облачных функций для Опорному пункту. Также проверьте их Google Cloud Node API Documentation

обходной путь может заключаться в создании файла (т. е. списка.txt) ничего внутри, в этом файле вы можете установить пользовательские метаданные (то есть Map) со списком всех URL-адресов файла.
Так что если вам нужно downlaod все файлы в fodler вы сначала загрузить метаданные списка.txt файл, затем вы перебираете пользовательские данные и загрузить все файлы с URL-адресами на карте.

Я также столкнулся с этой проблемой, когда работал над своим проектом. Я действительно хочу, чтобы они предоставили метод end api. Во всяком случае, вот как я это сделал: При загрузке изображения в хранилище Firebase создайте объект и одновременно передайте его в базу данных Firebase. Этот объект содержит URI загрузки изображения.

trailsRef.putFile(file).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
        @Override
        public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
            Uri downloadUri = taskSnapshot.getDownloadUrl();
            DatabaseReference myRef = database.getReference().child("trails").child(trail.getUnique_id()).push();
            Image img = new Image(trail.getUnique_id(), downloadUri.toString());
            myRef.setValue(img);
        }
    });

позже, когда вы хотите, чтобы загрузить изображения из папки, вы просто перебираете файлы в этой папке. Эта папка имеет то же имя как "папка" в хранилище Firebase, но вы можете назвать их так, как хотите. Я положил их в отдельную нить.

 @Override
protected List<Image> doInBackground(Trail... params) {

    String trialId = params[0].getUnique_id();
    mDatabase = FirebaseDatabase.getInstance().getReference();
    mDatabase.child("trails").child(trialId).addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            images = new ArrayList<>();
            Iterator<DataSnapshot> iter = dataSnapshot.getChildren().iterator();
            while (iter.hasNext()) {
                Image img = iter.next().getValue(Image.class);
                images.add(img);
            }
            isFinished = true;
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

теперь у меня есть список объектов, содержащих URI для каждого изображения, я могу делать с ними все, что захочу. Чтобы загрузить их в imageView, я создал еще один поток.

    @Override
protected List<Bitmap> doInBackground(List<Image>... params) {

    List<Bitmap> bitmaps = new ArrayList<>();

    for (int i = 0; i < params[0].size(); i++) {
        try {
            URL url = new URL(params[0].get(i).getImgUrl());
            Bitmap bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
            bitmaps.add(bmp);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return bitmaps;
}

Это возвращает список растровых изображений, когда он заканчивается, я просто прикрепляю их к ImageView в основной деятельности. Ниже методы @Override, потому что у меня есть созданные интерфейсы и слушайте для завершения в других потоках.

    @Override
public void processFinishForBitmap(List<Bitmap> bitmaps) {
    List<ImageView> imageViews = new ArrayList<>();
    View v;
    for (int i = 0; i < bitmaps.size(); i++) {
        v = mInflater.inflate(R.layout.gallery_item, mGallery, false);
        imageViews.add((ImageView) v.findViewById(R.id.id_index_gallery_item_image));
        imageViews.get(i).setImageBitmap(bitmaps.get(i));
        mGallery.addView(v);
    }
}

обратите внимание, что мне нужно сначала дождаться возврата изображения списка, а затем вызвать поток для работы с растровым изображением списка. В этом случае изображение содержит URI.

    @Override
public void processFinish(List<Image> results) {
    Log.e(TAG, "get back " + results.size());

    LoadImageFromUrlTask loadImageFromUrlTask =  new LoadImageFromUrlTask();
    loadImageFromUrlTask.delegate = this;
    loadImageFromUrlTask.execute(results);
}

надеюсь, кто-то найдет это полезным. Он также будет служить линией гильдии для меня в будущем тоже.

еще один способ добавить изображение в базу данных с помощью облачной функции для отслеживания каждого загруженного изображения и сохранения его в базе данных.

exports.fileUploaded = functions.storage.object().onChange(event => {

    const object = event.data; // the object that was just uploaded
    const contentType = event.data.contentType; // This is the image Mimme type\

    // Exit if this is triggered on a file that is not an image.
    if (!contentType.startsWith('image/')) {
        console.log('This is not an image.');
        return null;
    }

    // Get the Signed URLs for the thumbnail and original image.
    const config = {
        action: 'read',
        expires: '03-01-2500'
    };

    const bucket = gcs.bucket(event.data.bucket);
    const filePath = event.data.name;
    const file = bucket.file(filePath);

    file.getSignedUrl(config, function(err, fileURL) {
        console.log(fileURL);
        admin.database().ref('images').push({
            src: fileURL
        });
    });
});

полный код : https://gist.github.com/bossly/fb03686f2cb1699c2717a0359880cf84

для узла js, я использовал этот код

const Storage = require('@google-cloud/storage');
const storage = new Storage({projectId: 'PROJECT_ID', keyFilename: 'D:\keyFileName.json'});
const bucket = storage.bucket('project.appspot.com'); //gs://project.appspot.com
bucket.getFiles().then(results => {
    const files = results[0];
    console.log('Total files:', files.length);
    files.forEach(file => {
      file.download({destination: `D:\${file}`}).catch(error => console.log('Error: ', error))
    });
}).catch(err => {
    console.error('ERROR:', err);
  });

чтобы сделать это с JS

вы можете добавить их непосредственно в контейнер div, или вы можете нажать их в массив. Ниже показано, как добавить их в div.

1) при хранении изображений в хранилище создайте ссылку на изображение в базе данных firebase со следующей структурой

/images/(imageName){
   description: "" , 
   imageSrc : (imageSource) 
}

2) При загрузке документа извлеките все исходные URL-адреса изображений из базы данных, а не из хранилища со следующим кодом

$(document).ready(function(){

var query = firebase.database().ref('images/').orderByKey();
query.once("value").then(function(snapshot){

    snapshot.forEach(function(childSnapshot){

        var imageName = childSnapshot.key;
        var childData = childSnapshot.val();
        var imageSource = childData.url;

        $('#imageGallery').append("<div><img src='"+imageSource+"'/></div>");

    })
})
});

Вы можете использовать следующий код. Здесь я загружаю изображение в хранилище firebase, а затем сохраняю url-адрес загрузки изображения в базу данных firebase.

//getting the storage reference
            StorageReference sRef = storageReference.child(Constants.STORAGE_PATH_UPLOADS + System.currentTimeMillis() + "." + getFileExtension(filePath));

            //adding the file to reference 
            sRef.putFile(filePath)
                    .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                        @Override
                        public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                            //dismissing the progress dialog
                            progressDialog.dismiss();

                            //displaying success toast 
                            Toast.makeText(getApplicationContext(), "File Uploaded ", Toast.LENGTH_LONG).show();

                            //creating the upload object to store uploaded image details 
                            Upload upload = new Upload(editTextName.getText().toString().trim(), taskSnapshot.getDownloadUrl().toString());

                            //adding an upload to firebase database 
                            String uploadId = mDatabase.push().getKey();
                            mDatabase.child(uploadId).setValue(upload);
                        }
                    })
                    .addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception exception) {
                            progressDialog.dismiss();
                            Toast.makeText(getApplicationContext(), exception.getMessage(), Toast.LENGTH_LONG).show();
                        }
                    })
                    .addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
                        @Override
                        public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
                            //displaying the upload progress 
                            double progress = (100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount();
                            progressDialog.setMessage("Uploaded " + ((int) progress) + "%...");
                        }
                    });

теперь, чтобы получить все изображения, хранящиеся в базе данных firebase вы можете использовать

//adding an event listener to fetch values
        mDatabase.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot snapshot) {
                //dismissing the progress dialog 
                progressDialog.dismiss();

                //iterating through all the values in database
                for (DataSnapshot postSnapshot : snapshot.getChildren()) {
                    Upload upload = postSnapshot.getValue(Upload.class);
                    uploads.add(upload);
                }
                //creating adapter
                adapter = new MyAdapter(getApplicationContext(), uploads);

                //adding adapter to recyclerview
                recyclerView.setAdapter(adapter);
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                progressDialog.dismiss();
            }
        });

для более подробной информации вы можете увидеть мой пост Пример Хранения Firebase.

Итак, у меня был проект, который требовал загрузки активов из хранилища firebase, поэтому мне пришлось решить эту проблему самостоятельно. Вот как:

1 - Во-первых, сделать модель данных, например class Choice{}, в этом классе определяет строковую переменную с именем image Name, так что это будет так

class Choice {
    .....
    String imageName;
}

2-из базы данных / базы данных firebase перейдите и жестко Закодируйте имена изображений для объектов, поэтому, если у вас есть имя изображения под названием Apple.png, создайте объект, который будет

Choice myChoice = new Choice(...,....,"Apple.png");

3- Теперь, получить ссылку на активы в вашем хранилище firebase, который будет что-то вроде этого

gs://your-project-name.appspot.com/

вот так

4 - наконец, инициализируйте ссылку на хранилище firebase и начните получать файлы по циклу, подобному этому

storageRef = storage.getReferenceFromUrl(firebaseRefURL).child(imagePath);

File localFile = File.createTempFile("images", "png");
storageRef.getFile(localFile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {

@Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
    //Dismiss Progress Dialog\
}

5 - Вот это

для Android лучшая практика-использовать FirebaseUI и Glide.

вам нужно добавить, что на вашем gradle/app для того, чтобы получить библиотеку. Обратите внимание, что он уже скользит по нему!

implementation 'com.firebaseui:firebase-ui-storage:4.1.0'

а потом в вашем коде использовать

// Reference to an image file in Cloud Storage
StorageReference storageReference = FirebaseStorage.getInstance().getReference();

// ImageView in your Activity
ImageView imageView = findViewById(R.id.imageView);

// Download directly from StorageReference using Glide
// (See MyAppGlideModule for Loader registration)
GlideApp.with(this /* context */)
        .load(storageReference)
        .into(imageView);

на самом деле это возможно, но только с Google Cloud API вместо одного из Firebase. Это потому, что хранилище Firebase-это Google Cloud Storage Bucket который может быть легко достигнут с помощью Google Cloud API, однако вам нужно использовать OAuth для аутентификации вместо Firebase one.