如何在 Firebase 应用中获取 Cloud Storage 中所有文件的列表?

Posted

技术标签:

【中文标题】如何在 Firebase 应用中获取 Cloud Storage 中所有文件的列表?【英文标题】:How to get a list of all files in Cloud Storage in a Firebase app? 【发布时间】:2016-09-17 00:50:28 【问题描述】:

我正在上传图片,一切正常,但我有 100 张图片,我想在我的View 中显示所有图片,因为我在一个文件夹中获得了完整的图片列表,我可以找不到这项工作的任何 API。

【问题讨论】:

【参考方案1】:

因为 javascript release 6.1、ios release 6.4 和 android release version 18.1 的 Firebase SDK 都有列出文件的方法。

documentation 到目前为止有点稀疏,所以我建议查看Rosário's answer 了解详细信息。


以前的答案,因为这种方法有时仍然有用:

Firebase SDK 目前没有 API 调用来列出应用内 Cloud Storage 文件夹中的所有文件。如果您需要此类功能,则应将文件的元数据(例如下载 URL)存储在可以列出它们的位置。 Firebase Realtime Database 和 Cloud Firestore 非常适合此操作,您还可以轻松地与他人共享 URL。

您可以在我们的FriendlyPix 示例应用程序中找到一个很好的(但有些复杂的)示例。网页版的相关代码是here,但也有iOS和Android版本。

【讨论】:

你打算在 Firebase 上实现这个吗? 如果我需要将所有存储文件的 URL 保留在实时数据库中,那么在存储中具有文件夹层次结构的目的是什么?所有文件,具有唯一名称,可以存储在同一级别,根本不需要文件夹!你看,这很矛盾!!!基本上,文件夹层次结构背后的主要原理是通配符查询,而无需事先了解文件夹中的内容,而您没有合理地提供这些信息。 Firebase Storage 建立在 Google Cloud Storage 的基础上,正如您所说:它将所有对象存储在一个长列表中。 Firebase 存储在此之上建模了一个层次结构,无可否认,这是一种泄漏的抽象。在 Firebase 存储中使用文件夹的常见原因是为了逻辑数据分离和基于文件夹结构制定安全规则。 如果在上传后和将downloadUrl保存到数据库之前用户连接丢失怎么办?在这种情况下,我们如何发现文件夹中的现有文件? 现在呢? 2018 年有没有直接的 API?【参考方案2】:

截至 2019 年 5 月,适用于 Cloud Storage 的 Firebase SDK 的 version 6.1.0 现在支持列出存储分区中的所有对象。您只需在Reference 中调用listAll()

    // Since you mentioned your images are in a folder,
    // we'll create a Reference to that folder:
    var storageRef = firebase.storage().ref("your_folder");


    // Now we get the references of these images
    storageRef.listAll().then(function(result) 
      result.items.forEach(function(imageRef) 
        // And finally display them
        displayImage(imageRef);
      );
    ).catch(function(error) 
      // Handle any errors
    );

    function displayImage(imageRef) 
      imageRef.getDownloadURL().then(function(url) 
        // TODO: Display the image on the UI
      ).catch(function(error) 
        // Handle any errors
      );
    

注意,要使用此功能,您必须选择加入version 2 of Security Rules,这可以通过将rules_version = '2'; 设置为您的安全规则的第一行来完成:

    rules_version = '2';
    service firebase.storage 
      match /b/bucket/o 
        match /allPaths=** 

我建议您查看docs 以供进一步参考。

另外,根据setup,在第 5 步中,Node.js 不允许使用此脚本,因为 require("firebase/app"); 不会将 firebase.storage() 作为函数返回。这只能使用import * as firebase from 'firebase/app'; 来实现。

【讨论】:

你用的是哪个插件 @azheen 我假设您正在使用 Flutter。不幸的是,这在 Flutterfire 上尚不可用。您可以在this issue 上跟踪它 我在 firebase 存储规则中添加了 rules_version = '2' 文本,但是当文件夹有单个图像时 listAll 不返回任何路径,但如果文件夹中有 2 个文件,则它可以正常工作。我正在使用 Xamarin.iOS,你知道如何解决这个问题吗?【参考方案3】:

自 2017 年 3 月起:随着 Firebase Cloud Functions 的加入,以及 Firebase 与 Google Cloud 的更深入集成,这现在成为可能。

借助 Cloud Functions,您可以使用 Google Cloud Node 包在 Cloud Storage 上执行 epic 操作。下面是一个将所有文件 URL 从 Cloud Storage 获取到数组中的示例。每次将内容保存到谷歌云存储时都会触发此功能。

注意 1:这是一个计算量相当大的操作,因为它必须循环遍历存储桶/文件夹中的所有文件。

注 2:我写这个只是作为一个例子,没有在承诺等方面提供太多细节。只是为了给出一个想法。

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

// let's trigger this function with a 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 

  // this is just for the sake of this example. Ideally you should get the path from the object that is uploaded :)
  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);
      );
    );

  );

);

我希望这会给你一个大致的想法。如需更好的云功能示例,请查看Google's Github repo full of Cloud Functions samples for Firebase。还可以查看他们的Google Cloud Node API Documentation

【讨论】:

这太愚蠢了,firebase 不只是将此 api 添加到 firebase sdk 中 @Thaina 我认为这与规模有关。他们不仅要考虑小型应用程序,还要考虑巨头。如果一个路径有数千个文件怎么办。这个操作会消耗大量的计算能力,并且对于每个看似无辜和简单的调用都必须引用一个数据库。我对大规模使用 Firebase 的了解越深,我就越能理解为什么会做出某些妥协。 在这个 gcs api 中它也有限制和分页。API 消费者有责任了解风险并尝试选择可以扩展的方法。但是过度保护,所以削减我们的选择并不是一个好的决定。如果真的很贵,他们可以收取重载费用 这应该是最佳答案!感谢您的提醒。目前,语法与您的示例不同。您必须像这样链接.then,而不是发送回调作为参数:this.bucket .getFiles( prefix: 'path/to/directory' ) .then((arr) => ) @JPLew 不客气 :) 关于语法,它们仅在排除回调时才返回承诺。因此,使用您喜欢的任何一种都是安全的。在此处查看示例:cloud.google.com/nodejs/docs/reference/storage/1.3.x/…【参考方案4】:

由于没有列出语言,我将在 Swift 中回答这个问题。我们强烈建议同时使用 Firebase 存储和 Firebase 实时数据库来完成下载列表:

共享:

// 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)
  )
)

有关详细信息,请参阅Zero to App: Develop with Firebase,它是associated source code,了解如何执行此操作的实际示例。

【讨论】:

但是如何使用 Cloud Firestore 获得相同的结果?)【参考方案5】:

我在做项目时也遇到了这个问题。我真的希望他们提供一个结束 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);
    

请注意,我必须先等待返回列表图像,然后再调用线程处理列表位图。在这种情况下,Image 包含 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);

希望有人觉得它有帮助。它也将成为我未来的公会路线。

【讨论】:

【参考方案6】:

结合这篇文章和here 的一些答案,并经过一些个人研究,对于带有打字稿的NodeJS,我设法通过使用firebase-admin 来实现这一点:

import * as admin from 'firebase-admin';
const getFileNames = () => 
  admin.storage().bucket().getFiles(autoPaginate: false).then(([files]: any) => 
    const fileNames = files.map((file: any) => file.name);
    return fileNames;
  )
 

就我而言,我还需要从 firebase 存储中获取特定文件夹中的所有文件。根据google storage,文件夹不存在,而是一种命名约定。无论如何,我通过在getFiles 函数调用中添加 prefix: $folderName, autoPaginate: false 来设法做到这一点(没有将每个文件的完整路径保存到数据库中):

...
const getFileNames = (folderName: string) => 
  admin.storage().bucket().getFiles( prefix: `$folderName`, autoPaginate: false )
    .then(([files]: any) => 
    ...

【讨论】:

【参考方案7】:

您可以通过 listAll() 方法列出 firebase 存储目录中的文件。 要使用这种方法,必须实现这个版本的 firebase 存储。 'com.google.firebase:firebase-storage:18.1.1'

https://firebase.google.com/docs/storage/android/list-files

请记住,将安全规则升级到版本 2。

【讨论】:

【参考方案8】:

一种解决方法是创建一个内部没有任何内容的文件(即 list.txt),在此文件中,您可以使用所有文件 URL 的列表设置自定义元数据(即 Map)。 因此,如果您需要下载文件夹中的所有文件,您首先下载 list.txt 文件的元数据,然后遍历自定义数据并下载地图中包含 URL 的所有文件。

【讨论】:

是的,这是一种解决方法,但无法处理对单个 list.txt 的并发写入【参考方案9】:

另一种使用 Cloud Function 将图像添加到数据库的方法来跟踪每个上传的图像并将其存储在数据库中。

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

【讨论】:

【参考方案10】:

对于node 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);
  );

【讨论】:

你拯救了我的一天!!【参考方案11】:

实际上这是可能的,但只能使用 Google Cloud API 而不是 Firebase 的。这是因为 Firebase 存储是 Google Cloud Storage Bucket,可以通过 Google Cloud API 轻松访问,但是您需要使用 OAuth 进行身份验证而不是 Firebase 的。

【讨论】:

【参考方案12】:

扩展 Rosário Pereira Fernandes 的答案,以获取 JavaScript 解决方案:

    在你的机器上安装 firebase
npm install -g firebase-tools

    在 firebase 初始化时将 JavaScript 设置为默认语言 在创建项目的根文件夹执行 npm installs
   npm install --save firebase
   npm install @google-cloud/storage
   npm install @google-cloud/firestore
   ... <any other dependency needed>
    在您的项目中添加非默认依赖项,例如
    "firebase": "^6.3.3",
    "@google-cloud/storage": "^3.0.3"

functions/package.json


  "name": "functions",
  "description": "Cloud Functions for Firebase",
  "scripts": 
    "lint": "eslint .",
    "serve": "firebase serve --only functions",
    "shell": "firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  ,
  "engines": 
    "node": "10"
  ,
  "dependencies": 
    "@google-cloud/storage": "^3.0.3",
    "firebase": "^6.3.3",
    "firebase-admin": "^8.0.0",
    "firebase-functions": "^3.1.0"
  ,
  "devDependencies": 
    "eslint": "^5.12.0",
    "eslint-plugin-promise": "^4.0.1",
    "firebase-functions-test": "^0.1.6"
  ,
  "private": true


    创建某种listAll 函数

index.js

var serviceAccount = require("./key.json");
const functions = require('firebase-functions');

const images = require('./images.js');

var admin = require("firebase-admin");

admin.initializeApp(
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "https://<my_project>.firebaseio.com"
);

const bucket = admin.storage().bucket('<my_bucket>.appspot.com')

exports.getImages = functions.https.onRequest((request, response) => 
    images.getImages(bucket)
        .then(urls => response.status(200).send( data:  urls  ))
        .catch(err => console.error(err));
)

images.js

module.exports = 
    getImages


const query = 
    directory: 'images'
;

function getImages(bucket) 
    return bucket.getFiles(query)
        .then(response => getUrls(response))
        .catch(err => console.error(err));


function getUrls(response) 
    const promises = []
    response.forEach( files => 
        files.forEach (file => 
            promises.push(getSignedUrl(file));
        );
    );
    return Promise.all(promises).then(result => getParsedUrls(result));


function getSignedUrl(file) 
    return file.getSignedUrl(
        action: 'read',
        expires: '09-01-2019'
    )


function getParsedUrls(result) 
    return JSON.stringify(result.map(mediaLink => createMedia(mediaLink)));


function createMedia(mediaLink) 
    const reference = ;
    reference.mediaLink = mediaLink[0];
    return reference;


    执行firebase deploy上传你的云函数 Call 应用中的自定义函数

build.gradle

dependencies 
...
  implementation 'com.google.firebase:firebase-functions:18.1.0'
...

kotlin 类

  private val functions = FirebaseFunctions.getInstance()
  val cloudFunction = functions.getHttpsCallable("getImages")
  cloudFunction.call().addOnSuccessListener ...

关于此功能的进一步开发,我遇到了一些问题,可能会发现here。

【讨论】:

【参考方案13】:

我正在使用AngularFire 并使用以下内容获取所有downloadURL

getPhotos(id: string): Observable<string[]> 
    const ref = this.storage.ref(`photos/$id`)
    return ref.listAll().pipe(switchMap(list => 
      const calls: Promise<string>[] = [];
      list.items.forEach(item => calls.push(item.getDownloadURL()))
      return Promise.all(calls)
    ));

【讨论】:

【参考方案14】:

我遇到了同样的问题,我的更复杂。

管理员会将音频和 pdf 文件上传到存储中:

audios/season1、season2.../class1、class 2/.mp3 文件

书籍/.pdf 文件

Android 应用需要获取子文件夹和文件的列表。

解决方案是在存储上捕获上传事件,并使用云功能在 Firestore 上创建相同的结构。

第 1 步:在 firestore 上手动创建“存储”集合和“音频/书籍”文档

第 2 步:设置云功能

可能需要大约 15 分钟:https://www.youtube.com/watch?v=DYfP-UIKxH0&list=PLl-K7zZEsYLkPZHe41m4jfAxUi0JjLgSM&index=1

第 3 步:使用云功能捕捉上传事件

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp(functions.config().firebase);
const path = require('path');

export const onFileUpload = functions.storage.object().onFinalize(async (object) => 
        let filePath = object.name; // File path in the bucket.
        const contentType = object.contentType; // File content type.
        const metageneration = object.metageneration; // Number of times metadata has been generated. New objects have a value of 1.
        if (metageneration !== "1") return;

        // Get the file name.
        const fileName = path.basename(filePath);
        filePath = filePath.substring(0, filePath.length - 1);
        console.log('contentType ' + contentType);
        console.log('fileName ' + fileName);
        console.log('filePath ' + filePath);
        console.log('path.dirname(filePath) ' + path.dirname(filePath));
        filePath = path.dirname(filePath);
        const pathArray = filePath.split("/");
        let ref = '';
        for (const item of pathArray) 
            if (ref.length === 0) 
                ref = item;
            
            else 
                ref = ref.concat('/sub/').concat(item);
            
        
        
        ref = 'storage/'.concat(ref).concat('/sub')
        admin.firestore().collection(ref).doc(fileName).create()
                .then(result => console.log('onFileUpload:updated'))
                .catch(error => 
                    console.log(error);
                );
    );

第 4 步:使用 Firestore 检索 Android 应用上的文件夹/文件列表

private static final String STORAGE_DOC = "storage/";
    public static void getMediaCollection(String path, OnCompleteListener onCompleteListener) 
        String[] pathArray = path.split("/");
        String doc = null;
        for (String item : pathArray) 
            if (TextUtils.isEmpty(doc)) doc = STORAGE_DOC.concat(item);
            else doc = doc.concat("/sub/").concat(item);
        
        doc = doc.concat("/sub");

        getFirestore().collection(doc).get().addOnCompleteListener(onCompleteListener);
    

第五步:获取下载地址

public static void downloadMediaFile(String path, OnCompleteListener<Uri> onCompleteListener) 
        getStorage().getReference().child(path).getDownloadUrl().addOnCompleteListener(onCompleteListener);
    

注意

我们必须为每个项目添加“子”集合,因为 firestore 不支持检索集合列表。

我花了 3 天时间才找到解决方案,希望最多用 3 个小时。

【讨论】:

与我正在处理的场景完全相同。任何人都可以给我发送颤振代码吗?因为我只需要上传一批文件,而不是下载。 Flutter SDK(飞镖语言) cloud firestore 还不支持flutter firebase.google.com/docs/firestore。快速的方法是使用云函数编写 API,然后像往常一样通过 restful 访问这些 API。熟悉云功能可能需要几个小时,这些培训视频很容易下咽:D youtube.com/…【参考方案15】:

用 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>");

    )
)
);

【讨论】:

【参考方案16】:

您可以使用以下代码。在这里,我将图像上传到 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 Storage Example

【讨论】:

我在链接中按照您的示例进行操作,但是 RecyclerView 中的 Firebase 未显示图像【参考方案17】:
#In Python

import firebase_admin
from firebase_admin import credentials
from firebase_admin import storage
import datetime
import urllib.request


def image_download(url, name_img) :
    urllib.request.urlretrieve(url, name_img)

cred = credentials.Certificate("credentials.json")

# Initialize the app with a service account, granting admin privileges
app = firebase_admin.initialize_app(cred, 
    'storageBucket': 'YOURSTORAGEBUCKETNAME.appspot.com',
)
url_img = "gs://YOURSTORAGEBUCKETNAME.appspot.com/"
bucket_1 = storage.bucket(app=app)
image_urls = []

for blob in bucket_1.list_blobs():
    name = str(blob.name)
    #print(name)
    blob_img = bucket_1.blob(name)
    X_url = blob_img.generate_signed_url(datetime.timedelta(seconds = 300), method='GET')
    #print(X_url)
    image_urls.append(X_url)


PATH = ['Where you want to save the image']
for path in PATH:
    i = 1
    for url  in image_urls:
        name_img = str(path + "image"+str(i)+".jpg")
        image_download(url, name_img)
        i+=1

【讨论】:

不需要API你只需要一个简单的Python类和blob关键字【参考方案18】:

在斯威夫特中

    public func downloadData() async 
        
        let imagesRef = storage.child("pictures/")
        do 
            let storageReference = try await storage.root().child("pictures").listAll()
            print("storageReference: \(storageReference.items)")
         catch 
            print(error)
        

输出

[
gs://<your_app_name>.appspot.com/pictures/IMG_1243.JPG, 
gs://<your_app_name>.appspot.com/pictures/IMG_1244.JPG, 
gs://<your_app_name>.appspot.com/pictures/IMG_1245.JPG, 
gs://<your_app_name>.appspot.com/pictures/IMG_1246.JPG
]

Here is the reference

【讨论】:

【参考方案19】:

所以我有一个项目需要从 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/

like this one

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-就是这样

【讨论】:

【参考方案20】:

对于 Android,最好的做法是使用 FirebaseUI 和 Glide。

您需要将其添加到您的 gradle/app 中才能获取该库。请注意,它上面已经有 Glide!

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);

【讨论】:

以上是关于如何在 Firebase 应用中获取 Cloud Storage 中所有文件的列表?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Firestore 在 Cloud Functions for Firebase 中获取服务器时间戳?

如何从 Cloud Function 获取 Firebase 项目名称或 ID

从请求中获取用户信息到 Firebase 中的 Cloud Function

如何在 Cloud Functions 存储触发器中获取经过身份验证的 Firebase 用户的 uid

如何使用 graphql 从 Firebase 使用 Flutter 从 Cloud Firestore 获取数据?

如何在flutter中从firebase获取数据