简体   繁体   中英

Uploading Multiple Images to Firebase Storage, and Then Calling the Download URL's to Firebase Database

I am trying to upload multiple images to firebase storage simultaneously and then call them down into a firebase database. I have this working with singular images, but I am not sure how I need to modify my code to allow multiple images. When I select multiple images to be uploaded, they successfully upload to firebase storage, however, only the first image uploaded will be assigned to the featuredImage array and therefore displayed. Any help would be much appreciated.

Here is my code:

class OtherEdit extends Component {
constructor(props) {
    super(props);
    
    this.state={
        id: '',
        info: {
            title: '',
            subtitle: ''
        },
        article: {
            featuredImage: []
        }
    }
}

...

uploadImageCallBack = (e) => {
    return new Promise(async(resolve, reject) => {
        const file = e.target.files[0]
        const fileName = uuidv4()
        storageRef.ref().child("OtherMedia/" + fileName).put(file)
        .then( async snapshot => {
            
            const downloadURL = await storageRef.ref().child("OtherMedia/" +fileName).getDownloadURL()

            resolve({
                success: true,
                data: {link: downloadURL},
                
            })
        })
    })
}

...

<FormGroup className='edit-featured-image'> Featured images
                            <Input type="file" multiple accept='image/*' className="image-uploader"
                            onChange={async (e) => {
                                const uploadState = await this.uploadImageCallBack(e)
                                if(uploadState.success) {
                                   await this.setState({
                                        hasFeaturedImage: true,
                                        article: {
                                            ...this.state.article,
                                            featuredImage: uploadState.data.link
                                        }
                                        
                                    })
                                    
                                }
                            }}> 
                            </Input>
                            <div className='image'>
                            {
                                this.state.hasFeaturedImage ?
                                    <img src={this.state.article.featuredImage} /> : ''
                            }</div>
                        </FormGroup>

You could loop through all files selected and upload each file in a promise, then wait for all promises to resolve, like so:

const uploadImageCallBack = async (e) => {
  const uploads = [];
  const promises = [];

  e.target.files.forEach(file => {

    const path = storageRef.ref().child(`OtherMedia/${uuidv4()}`);
    const uploadPromise = path.put(file).then(async snapshot => {
      /** @TODO it's a good idea to do some error handling here */
      const downloadURL = await path.getDownloadURL();
      uploads.push({
        success: true,
        data: { link: downloadURL },
      });
    });
    promises.push(uploadPromise);
    
  });

  await Promise.all(promises); // Wait for all promises to complete
  return uploads;
};

Now you can update your state from the Input 's onChange :

<Input type="file" multiple accept='image/*' className="image-uploader"
  onChange={async (e) => {
    const uploads = await this.uploadImageCallBack(e);
    const featuredImages = uploads.filter(upload => upload.success).map(upload => upload.data.link);
    await this.setState({
      hasFeaturedImage: true,
        article: {
          ...this.state.article,
          featuredImages // I took the liberty to rename this to plural, as this is an array
        }
    });
  }}>
</Input>

You might want to ditch your hasFeaturedImage state, as you could simply display al images like this (if the array is empty, no images will be displayed).

{
  this.state.article.featuredImages.map((imageSrc, index) => (
    <img key={`image-${index}`} src={imageSrc} />
  ))
}

Note: I have not tested the code above, so feel free to comment if there's something wrong and I'll update it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM