title: Retrieving images from Firebase Cloud Storage
body: <p>I'm creating a chat app in <strong>Angular 4</strong> where people can send chat messages (text) and media. I'm using <strong>Firebase</strong> to store all conversations, messages and members. And it's <strong>Cloud Storage</strong> to store files.</p>
  
  <p>I've already stored some messages with media (images) attached to them, but I'm not able to load these images in the conversation view.</p>
  
  <p>According to <a href="https://firebase.google.com/docs/storage/web/download-files" rel="nofollow noreferrer">https://firebase.google.com/docs/storage/web/download-files</a> I'd be able to download these files via:</p>
  
  <pre><code>const storageRef = this.firebaseApp.storage().ref().child(message.media.path + message.media.filename);
  storageRef.getDownloadURL().then(url =&gt; console.log(url));
  </code></pre>
  
  <p>Which does work, since I can see the url in the console output, and clicking on it shows me my uploaded image.</p>
  
  <p><strong>Example output url:</strong></p>
  
  <pre><code>https://firebasestorage.googleapis.com/v0/b/&lt;databasename&gt;.appspot.com/o/messages%2Fconversation1%2Fmessage1%2Fmedia%2F91615172-find-a-lump-on-cats-skin-632x475.jpg?alt=media&amp;token=&lt;sometoken&gt;
  </code></pre>
  
  <p>My question is how I can show this one in my message.component.html template.
  I've tried the following:</p>
  
  <blockquote>
    <p>Attempt 1:</p>
  </blockquote>
  
  <p><strong>message.component.html:</strong></p>
  
  <pre><code>&lt;img src="{{message.media?.url}}"&gt;
  </code></pre>
  
  <p><strong>chat.service.ts:</strong></p>
  
  <pre><code>public retrieveMessages(conversationId) {
      this.messages = this.db.list('messages/' + conversationId, {query: {limitToLast: 10}});
      this.messages.subscribe(messages =&gt; {
          this.appendMessagesWithMediaURL(messages);
      });
  }
  
  public appendMessagesWithMediaURL(messages) {
      for (const message of messages) {
          if (message.media) { // message has media
              this.firebaseApp.storage().ref().child(message.media.path + message.media.filename).getDownloadURL().then(url =&gt; message.media.url = url);
          }
      }
  }
  </code></pre>
  
  <p><em>This will set all 'src' attributes to 'unknown'. I think this is because the .url property does not exist when the view loads (messages will be retrieved first, THEN we declare and initialize the .url property).</em></p>
  
  <blockquote>
    <p>Attempt 2:</p>
  </blockquote>
  
  <p><strong>message.component.html:</strong></p>
  
  <pre><code>&lt;img src="{{(chatService.getMediaURL(message) | async)}}"&gt;
  </code></pre>
  
  <p><strong>chat.service.ts:</strong></p>
  
  <pre><code>public getMediaURL(message) {
      return new Observable(observer =&gt; {
          if (message.media) {
              const storageRef = this.firebaseApp.storage().ref().child(message.media.path + message.media.filename);
              storageRef.getDownloadURL().then(url =&gt; observer.next(url));
          }
      });
  }
  </code></pre>
  
  <p><em>This makes my Angular app hang when I load the message.component. (RAM usage is >1GB in a few seconds and the tab isn't responding anymore.) Note that I'm only loading 10 messages, only 2 of them do have a media property with 1 single image (200KB each).</em></p>
  
  <blockquote>
    <p>Additional info</p>
  </blockquote>
  
  <p><strong>Firebase layout:</strong></p>
  
  <pre><code>"messages": {
      "conversation1": {
          "message1": {
              "content": "Hello World",
              "media": {
                  "path": "/messages/conversation1/message1/",
                  "filename": "picture.png",
                  "type": "image/jpeg"
              }
          }
      }
  }
  </code></pre>
  
  <p>Example that I used as reference for 'how to retrieve images': <a href="https://stackoverflow.com/questions/39067832/accessing-firebase-storage-with-angularfire2-angular2-rc-5">Accessing firebase.storage() with AngularFire2 (Angular2 rc.5)</a></p>
  
  <p><strong>Fragment of conversation.component.html</strong></p>
  
  <pre><code>&lt;!-- BEGIN Conversation  !--&gt;
  &lt;div class="chat-inner" id="my-conversation"&gt;
      &lt;!-- BEGIN Message  !--&gt;
          &lt;chassis-message *ngFor="let message of chatService.messages | async" [message]="message"&gt;&lt;/chassis-message&gt;
      &lt;!-- END Message  !--&gt;
  &lt;/div&gt;
  &lt;!-- BEGIN Conversation  !--&gt;
  </code></pre>
  
  <p><strong>Fragment of message.component.ts</strong></p>
  
  <pre><code>import { Component, Input } from '@angular/core';
  import { ChatService } from '../chat.service';
  
  @Component({
      selector: 'chassis-message',
      templateUrl: './message.component.html',
      styleUrls: ['./message.component.css'],
  })
  export class MessageComponent {
      @Input() message: any;
  
      constructor(private chatService: ChatService) {
      }
  }
  </code></pre>
  
  <blockquote>
    <p>Question</p>
  </blockquote>
  
  <p>What is the correct way to retrieve those images?</p>