จะรับรายการไฟล์ทั้งหมดใน Cloud Storage ในแอป Firebase ได้อย่างไร


107

ฉันกำลังอัปโหลดรูปภาพทุกอย่างใช้งานได้ดี แต่ฉันมี 100 ภาพและฉันต้องการแสดงทั้งหมดในของฉันViewเนื่องจากฉันได้รับรายการรูปภาพทั้งหมดในโฟลเดอร์ฉันไม่พบ API สำหรับสิ่งนี้ งาน.


คุณสามารถโพสต์โซลูชันโค้ดแบบเต็มได้ไหม
ISS

คำตอบ:


94

ตั้งแต่ Firebase SDK สำหรับJavaScript รุ่น 6.1 , iOS รุ่น 6.4และAndroid รุ่น 18.1ทั้งหมดมีวิธีการแสดงรายการไฟล์

ขณะนี้เอกสารมีข้อมูลค่อนข้างเบาบางดังนั้นฉันขอแนะนำให้ตรวจสอบคำตอบของRosárioเพื่อดูรายละเอียด


คำตอบก่อนหน้าเนื่องจากแนวทางนี้ยังคงมีประโยชน์ในบางครั้ง:

ขณะนี้ไม่มีการเรียก API ใน Firebase SDK เพื่อแสดงรายการไฟล์ทั้งหมดในโฟลเดอร์ Cloud Storage จากภายในแอป หากคุณต้องการฟังก์ชันดังกล่าวคุณควรจัดเก็บข้อมูลเมตาของไฟล์ (เช่น URL สำหรับดาวน์โหลด) ไว้ในที่ที่คุณสามารถแสดงรายการได้ ฐานข้อมูล Firebase เรียลไทม์และมีเมฆ FireStoreที่สมบูรณ์แบบสำหรับการนี้และช่วยให้คุณยังสามารถแบ่งปัน URL ที่มีคนอื่น ๆ

คุณสามารถค้นหาตัวอย่างที่ดี (แต่ค่อนข้างเกี่ยวข้อง) ของสิ่งนี้ในแอปตัวอย่างFriendlyPixของเรา รหัสที่เกี่ยวข้องสำหรับเวอร์ชันเว็บอยู่ที่นี่แต่ยังมีเวอร์ชันสำหรับ iOS และ Android


8
คุณจะนำสิ่งนี้ไปใช้กับ Firebase หรือไม่
ท่าเรือ

56
หากฉันต้องการเก็บ URL ของไฟล์ Storage ทั้งหมดของฉันไว้ใน Realtime Database จุดประสงค์ของการมีลำดับชั้นของโฟลเดอร์ใน Storage คืออะไร? ทุกไฟล์ที่มีชื่อเฉพาะสามารถจัดเก็บในระดับเดียวกันไม่ต้องใช้โฟลเดอร์เลย !!! เห็นมั้ยว่าขัดแย้ง !!! โดยพื้นฐานแล้วเหตุผลหลักที่อยู่เบื้องหลังลำดับชั้นของโฟลเดอร์คือการสืบค้นโดยใช้สัญลักษณ์แทนโดยไม่มีความรู้มาก่อนเกี่ยวกับสิ่งที่คุณมีในโฟลเดอร์ซึ่งคุณไม่ได้ระบุไว้อย่างไม่สมเหตุสมผล
abedfar

8
Firebase Storage สร้างขึ้นบน Google Cloud Storage ซึ่งทำสิ่งที่คุณพูดได้อย่างแม่นยำ: จัดเก็บวัตถุทั้งหมดไว้ในรายการเดียว Firebase Storage จะจำลองลำดับชั้นที่ด้านบนซึ่งเป็นที่ยอมรับว่าเป็นนามธรรมที่รั่วไหล สาเหตุทั่วไปในการใช้โฟลเดอร์ใน Firebase Storage คือเพื่อการแยกข้อมูลเชิงตรรกะและเพื่อสร้างกฎความปลอดภัยตามโครงสร้างโฟลเดอร์
Frank van Puffelen

8
จะเกิดอะไรขึ้นหากการเชื่อมต่อของผู้ใช้ขาดหายไปหลังจากอัปโหลดและก่อนบันทึก downloadUrl ลงในฐานข้อมูล เราจะค้นพบไฟล์ที่มีอยู่ในโฟลเดอร์ได้อย่างไร?
Oswaldo

11
แล้วตอนนี้ล่ะ ? มี API โดยตรงสำหรับสิ่งนี้ในปี 2018 หรือไม่?
Diaz diaz

55

ในเดือนพฤษภาคม 2019 Firebase SDK for Cloud Storage เวอร์ชัน 6.1.0รองรับการแสดงรายการวัตถุทั้งหมดจากที่เก็บข้อมูลแล้ว คุณก็จำเป็นต้องโทรlistAll()ในReference:

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

โปรดทราบว่าในการใช้ฟังก์ชันนี้คุณต้องเลือกใช้กฎความปลอดภัยเวอร์ชัน 2ซึ่งสามารถทำได้โดยสร้างrules_version = '2';บรรทัดแรกของกฎความปลอดภัยของคุณ:

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

ขอแนะนำให้ตรวจสอบเอกสารเพื่อใช้อ้างอิงเพิ่มเติม

นอกจากนี้ตามการตั้งค่าในขั้นตอนที่ 5 สคริปต์นี้ไม่ได้รับอนุญาตNode.jsเนื่องจากrequire("firebase/app");จะไม่กลับมาfirebase.storage()เป็นฟังก์ชัน ทำได้โดยใช้import * as firebase from 'firebase/app';ไฟล์.


คุณใช้ปลั๊กอินตัว
ไหน

@ azheen ฉันคิดว่าคุณกำลังใช้ Flutter น่าเสียดายที่สิ่งนี้ยังไม่พร้อมใช้งานใน Flutterfire คุณสามารถติดตามได้ในฉบับนี้
Rosário Pereira Fernandes

35

ตั้งแต่เดือนมีนาคม 2017:ด้วยการเพิ่มFirebase Cloud Functionsและการผสานรวมที่ลึกซึ้งยิ่งขึ้นของ Firebase กับ Google Cloud สิ่งนี้ทำได้แล้ว

ด้วยฟังก์ชั่ Cloud ที่คุณสามารถใช้แพคเกจ Google Cloud Node จะทำมหากาพย์การดำเนินงานเกี่ยวกับการจัดเก็บเมฆ ด้านล่างนี้เป็นตัวอย่างที่รับ URL ของไฟล์ทั้งหมดไปยังอาร์เรย์จาก Cloud Storage ฟังก์ชั่นนี้จะถูกเรียกใช้ทุกครั้งที่มีการบันทึกบางสิ่งลงในที่เก็บข้อมูลบนคลาวด์ของ Google

หมายเหตุ 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 Github repo เต็มรูปแบบของระบบคลาวด์สำหรับฟังก์ชั่นตัวอย่าง Firebase ตรวจสอบเอกสาร Google Cloud Node API


36
มันโง่เกินไปที่ firebase ไม่เพียงแค่เพิ่ม api นี้ลงใน
firebase

4
@ ไทยคิดว่ามันต้องเกี่ยวกับสเกล พวกเขาต้องคิดถึงไม่ใช่แค่แอพขนาดเล็ก แต่ยังรวมถึงแอพยักษ์ จะเกิดอะไรขึ้นถ้าเส้นทางมีไฟล์หลายพันไฟล์ การดำเนินการนี้จะใช้พลังงานในการประมวลผลมากและจะต้องอ้างถึงฐานข้อมูลสำหรับการโทรแต่ละครั้งที่ดูเหมือนไร้เดียงสาและเรียบง่าย ยิ่งฉันได้ใช้ Firebase ในระดับที่ลึกมากเท่าไหร่ฉันก็ยิ่งเข้าใจดีขึ้นว่าเหตุใดจึงมีการประนีประนอมบางอย่าง
johnozbay

1
ใน gcs api นี้ยังมีขีด จำกัด และเลขหน้าจากนั้นเป็นความรับผิดชอบของผู้บริโภค API ที่จะต้องทราบความเสี่ยงและพยายามเลือกวิธีการที่สามารถปรับขนาดได้ แต่การป้องกันมากเกินไปดังนั้นการตัดตัวเลือกของเราไม่ใช่การตัดสินใจที่ดี พวกเขาสามารถเรียกเก็บเงินสำหรับการบรรทุกหนักได้หากมีค่าใช้จ่ายจริง ๆ
Thaina

1
นี่น่าจะเป็นคำตอบอันดับต้น ๆ ! ขอบคุณสำหรับหัวขึ้น. ขณะนี้ไวยากรณ์แตกต่างจากตัวอย่างของคุณ แทนที่จะส่งการโทรกลับเป็นพารามิเตอร์คุณต้องต่อสายแบบ.thenนี้:this.bucket .getFiles({ prefix: 'path/to/directory' }) .then((arr) => {})
JP Lew

1
@JPLew ยินดีต้อนรับ :) เกี่ยวกับไวยากรณ์พวกเขาจะคืนสัญญาเฉพาะในกรณีที่ไม่รวมการโทรกลับ ดังนั้นจึงปลอดภัยที่จะใช้ตามที่คุณต้องการ ดูตัวอย่างได้ที่นี่: cloud.google.com/nodejs/docs/reference/storage/1.3.x/…
johnozbay

20

เนื่องจากไม่มีภาษาในรายการฉันจะตอบใน Swift เราขอแนะนำอย่างยิ่งให้ใช้ Firebase Storage และ Firebase Realtime Database ร่วมกันเพื่อทำรายการดาวน์โหลดให้สำเร็จ:

แชร์:

// 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: พัฒนาด้วย Firebaseและซอร์สโค้ดที่เกี่ยวข้องสำหรับตัวอย่างวิธีการใช้งานจริง


3
แต่ฉันจะได้ผลลัพธ์เดียวกันกับ Cloud Firestore ได้อย่างไร)
Max Kraev

5

วิธีแก้ปัญหาสามารถสร้างไฟล์ (เช่น list.txt) โดยไม่มีอะไรอยู่ข้างในในไฟล์นี้คุณสามารถตั้งค่าข้อมูลเมตาที่กำหนดเอง (นั่นคือ Map <String, String>) ด้วยรายการ URL ของไฟล์ทั้งหมด
ดังนั้นหากคุณต้องการดาวน์โหลดไฟล์ทั้งหมดใน fodler คุณต้องดาวน์โหลดข้อมูลเมตาของไฟล์ list.txt ก่อนจากนั้นคุณจะวนซ้ำข้อมูลที่กำหนดเองและดาวน์โหลดไฟล์ทั้งหมดด้วย URL ในแผนที่


4
ใช่นี่เป็นวิธีแก้ปัญหา แต่ไม่สามารถจัดการการเขียนพร้อมกันไปยัง list.txt เดียวได้
linquize

5

ฉันยังพบปัญหานี้เมื่อฉันทำงานในโครงการของฉัน ฉันต้องการให้พวกเขาระบุวิธี 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;
}

สิ่งนี้ส่งคืนรายการ Bitmap เมื่อเสร็จสิ้นฉันเพียงแค่แนบไฟล์เหล่านั้นเข้ากับ 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);
    }
}

โปรดทราบว่าฉันต้องรอให้ List Image ถูกส่งคืนก่อนจากนั้นจึงเรียกเธรดเพื่อทำงานบน List Bitmap ในกรณีนี้รูปภาพจะมี 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);
}

หวังว่าจะมีคนพบว่ามันเป็นประโยชน์ นอกจากนี้ยังจะเป็นสายกิลด์สำหรับตัวเองในอนาคตด้วย


5

อีกวิธีหนึ่งในการเพิ่มรูปภาพลงในฐานข้อมูลโดยใช้ฟังก์ชันคลาวด์เพื่อติดตามภาพที่อัปโหลดทุกภาพและจัดเก็บไว้ในฐานข้อมูล

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


5

สำหรับโหนด 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);
  });

คุณเพิ่งช่วยวันของฉัน !!
hugo blanc

5

คุณสามารถแสดงรายการไฟล์ในไดเร็กทอรีของหน่วยเก็บข้อมูล firebase โดยวิธี listAll () หากต้องการใช้วิธีนี้ต้องใช้พื้นที่เก็บข้อมูล firebase เวอร์ชันนี้ 'com.google.firebase: firebase-storage: 18.1.1'

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

โปรดทราบว่าอัปเกรดกฎความปลอดภัยเป็นเวอร์ชัน 2


3

อันที่จริงสิ่งนี้เป็นไปได้ แต่ต้องใช้Google Cloud APIแทนจาก Firebase เนื่องจาก Firebase Storage เป็นGoogle Cloud Storage Bucketซึ่งสามารถเข้าถึงได้อย่างง่ายดายด้วย Google Cloud APIs แต่คุณต้องใช้ OAuth สำหรับการตรวจสอบสิทธิ์แทน Firebase


3

ฉันประสบปัญหาเดียวกันของฉันยิ่งซับซ้อนมากขึ้น

ผู้ดูแลระบบจะอัปโหลดไฟล์เสียงและ pdf ไปยังที่จัดเก็บ:

  • ไฟล์เสียง / season1, season2 ... / class1, คลาส 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: ดึงรายการโฟลเดอร์ / ไฟล์บนแอพ Android โดยใช้ firestore

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

ขั้นตอนที่ 5: รับ url ดาวน์โหลด

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

บันทึก

เราต้องใส่คอลเลกชัน "ย่อย" ให้กับแต่ละรายการเนื่องจาก firestore ไม่รองรับการดึงรายการคอลเลกชัน

ฉันใช้เวลา 3 วันในการหาวิธีแก้ปัญหาหวังว่าคุณจะใช้เวลาไม่เกิน 3 ชั่วโมง

ไชโย


สถานการณ์เดียวกันกับที่ฉันกำลังทำอยู่ ใครช่วยส่งรหัสกระพือให้ฉันได้ไหม เพราะฉันต้องอัปโหลดไฟล์เป็นกลุ่มเท่านั้นไม่ใช่เพื่อดาวน์โหลด
Mahesh Peri

Flutter SDK (ภาษาปาเป้า)
Mahesh Peri

1
เมฆ FireStore ยังไม่ได้สนับสนุนการกระพือยังfirebase.google.com/docs/firestore แนวทางที่รวดเร็วคือการเขียน API โดยใช้ฟังก์ชันคลาวด์จากนั้นเข้าถึง API เหล่านี้ผ่านการพักผ่อนตามปกติ มันอาจจะใช้เวลาหลายชั่วโมงที่จะได้คุ้นเคยกับการทำงานของระบบคลาวด์เหล่านี้วิดีโอการฝึกอบรมค่อนข้างง่ายต่อการกลืน: D youtube.com/...
thanhbinh84

3

ขยายคำตอบของRosário Pereira Fernandesสำหรับโซลูชัน JavaScript:

  1. ติดตั้ง firebase บนเครื่องของคุณ
npm install -g firebase-tools

  1. ใน firebase init ตั้งJavaScriptเป็นภาษาเริ่มต้น
  2. บนโฟลเดอร์รูทของโปรเจ็กต์ที่สร้างขึ้นดำเนินการติดตั้ง npm
   npm install --save firebase
   npm install @google-cloud/storage
   npm install @google-cloud/firestore
   ... <any other dependency needed>
  1. เพิ่มการอ้างอิงที่ไม่ใช่ค่าเริ่มต้นในโครงการของคุณเช่น
    "firebase": "^6.3.3",
    "@google-cloud/storage": "^3.0.3"

ฟังก์ชัน / 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
}

  1. สร้างการเรียงลำดับของ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;
}

  1. ดำเนินการfirebase deployเพื่ออัปโหลดฟังก์ชันระบบคลาวด์ของคุณ
  2. เรียกใช้ฟังก์ชันที่กำหนดเองจากแอปของคุณ

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 {...}

เกี่ยวกับการพัฒนาต่อไปของคุณลักษณะนี้ฉันวิ่งเข้าไปในปัญหาที่อาจพบได้ที่นี่


2

เมื่อต้องการทำสิ่งนี้กับ 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>");

    })
})
});

2

คุณสามารถใช้รหัสต่อไปนี้ ที่นี่ฉันกำลังอัปโหลดภาพไปยังที่เก็บข้อมูลของ 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();
            }
        });

Fore รายละเอียดเพิ่มเติมสามารถดูโพสต์ของฉันFirebase ตัวอย่างการจัดเก็บข้อมูล


ฉันทำตามตัวอย่างของคุณในลิงค์ แต่ภาพไม่ปรากฏจาก Firebase ใน RecyclerView
Wolfiebae

1

ดังนั้นฉันจึงมีโครงการที่ต้องดาวน์โหลดเนื้อหาจากที่เก็บข้อมูลของ firebase ดังนั้นฉันจึงต้องแก้ปัญหานี้ด้วยตัวเอง นี่คือวิธี:

1- ขั้นแรกให้สร้างโมเดลข้อมูลเช่นclass Choice{}ในคลาสนั้นกำหนดตัวแปร String ที่เรียกว่า 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- นั่นแหล่ะ


1
#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
Milan Hazra

0

ฉันใช้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)
    }));
}

0

การรวมคำตอบบางส่วนจากโพสต์นี้และจากที่นี่และหลังจากการวิจัยส่วนตัวสำหรับ NodeJS ที่มี typescript ฉันสามารถทำได้โดยใช้ firebase-admin:

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

ในกรณีของฉันฉันต้องรับไฟล์ทั้งหมดจากโฟลเดอร์เฉพาะจากที่เก็บข้อมูล firebase ตามที่จัดเก็บข้อมูลของ Googleไม่มีโฟลเดอร์ แต่เป็นแบบแผนการตั้งชื่อ อย่างไรก็ตามฉันจัดการเพื่อการนี้โดยการเพิ่ม{ prefix: ${folderName}, autoPaginate: false }ที่getFilesฟังก์ชั่นอื่น ๆ :

getFiles({ prefix: `${folderName}`, autoPaginate: false })

-1

สำหรับ 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);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.