title: Downloading a file from remote and save it to an Android device
body: <p>What I'm trying to do is decouple how the file is downloaded from where I save it to aka the storage.</p>
  
  <p><strong>The code that works fine:</strong></p>
  
  <p>The following code downloads a file from remote and finally save it to the storage.</p>
  
  <pre><code>private fun downloadFile(url: URL): Observable&lt;Int&gt; {
  
      return Observable.create(fun(emitter)
      {
          var input: InputStream? = null
          var output: OutputStream? = null
          var connection: HttpURLConnection? = null
          val path = Environment.getExternalStorageDirectory().path
  
          try
          {
              connection = url.openConnection() as HttpURLConnection
  
              if (connection != null)
              {
                  connection.connect()
  
                  if (connection.responseCode != HttpURLConnection.HTTP_OK)
                  {
                      emitter.onError(IllegalStateException("&lt;HTTP Error&gt; ${connection.responseMessage}. Status code: ${connection.responseCode}."))
                      return
                  }
  
                  if (connection.contentType == null)
                  {
                      emitter.onError(IllegalStateException("&lt;HTTP Error&gt; Unsupported content-type."))
                      return
                  }
  
                  val fileLength = connection.contentLength
                  var fileext = MimeTypeMap.getSingleton().getExtensionFromMimeType(connection.contentType)
  
                  input = connection.inputStream
                  output = FileOutputStream("/$path/SmartTVMediaTest.$fileext")
                  val data = ByteArray(4096)
                  var totalBytesReceived: Int = 0
  
                  while (!emitter.isDisposed)
                  {
                      val receivedBytes: Int = input.read(data)
  
                      if (receivedBytes &lt; 0)
                      {
                          break
                      }
  
                      totalBytesReceived += receivedBytes
  
                      if (fileLength &gt; 0)
                      {
                          val portion = totalBytesReceived / fileLength.toFloat()
                          val percentage = portion * 100
                          emitter.onNext(percentage.toInt())
  
                          Log.d(TAG, "&lt;downloadFile&gt; $fileLength, $totalBytesReceived,  $percentage")
                      }
  
                      output.write(data, 0, receivedBytes)
                  }
  
                  emitter.onComplete()
              }
              else {
                  emitter.onError(IllegalStateException("&lt;HTTP Connection Error&gt; Unsupported connection type."))
              }
          }
          catch(ex: InterruptedException) {
              Log.d(TAG, "&lt;Thread&gt; Download cancelled.")
          }
          catch (ex: IOException)
          {
              emitter.onError(ex)
          }
          finally
          {
              input?.close()
              output?.close()
              connection?.disconnect()
          }
      })
  }
  </code></pre>
  
  <p><strong>The code that doesn't work:</strong></p>
  
  <p>So I started by creating a class that represents the chunks of data that are read from remote which looks like this:</p>
  
  <pre><code>public data class DownloadChunk(val data: ByteArray, val length: Int, val totalLength: Int)
  </code></pre>
  
  <p>Then I created the observable that downloads the file which looks like this:</p>
  
  <pre><code>public class DownloadServiceObservable
  {
      public fun download(url: URL): Observable&lt;DownloadChunk&gt;
      {
          return Observable.create(fun(emitter)
          {
              var input: InputStream? = null
              var connection: HttpURLConnection? = null
  
              try
              {
                  connection = url.openConnection() as HttpURLConnection
  
                  if (connection != null)
                  {
                      connection.connect()
  
                      if (connection.responseCode != HttpURLConnection.HTTP_OK)
                      {
                          emitter.onError(IllegalStateException("&lt;HTTP Error&gt; ${connection.responseMessage}. Status code: ${connection.responseCode}."))
                          return
                      }
  
                      if (connection.contentType == null)
                      {
                          emitter.onError(IllegalStateException("&lt;HTTP Error&gt; Unsupported content-type."))
                          return
                      }
  
                      val totalLength = connection.contentLength
  
                      input = connection.inputStream
  
                      val data = ByteArray(4096)
  
                      while (!emitter.isDisposed)
                      {
                          val length: Int = input.read(data)
  
                          if (length &lt; 0)
                          {
                              break
                          }
  
                          emitter.onNext(DownloadChunk(data, length, totalLength))
                      }
  
                      emitter.onComplete()
                  }
                  else
                  {
                      emitter.onError(IllegalStateException("&lt;HTTP Connection Error&gt; Unsupported connection type."))
                  }
              }
              catch(ex: InterruptedException)
              {
                  emitter.onError(ex)
              }
              finally
              {
                  input?.close()
                  connection?.disconnect()
              }
          })
      }
  }
  </code></pre>
  
  <p>Finally, I created an <code>Observer</code> that saves the file to the device which looks like this:</p>
  
  <pre><code>public class DownloadFileObserver: Observer&lt;DownloadChunk&gt;
  {
      private val _file: OutputStream
  
      public override fun onSubscribe(d: Disposable)
      {
      }
  
      public constructor(path: String)
      {
          _file = FileOutputStream(path)
      }
  
      public override fun onNext(chunk: DownloadChunk)
      {
          _file.write(chunk.data, 0, chunk.length)
      }
  
      public override fun onError(e: Throwable)
      {
          _file.close()
      }
  
      public override fun onComplete()
      {
          _file.close()
      }
  }
  </code></pre>
  
  <p><strong>The Problem:</strong></p>
  
  <p>The file that gets created by <code>DownloadFileObserver</code> is corrupted so the first assumption I had is that the order of onNext is not guaranteed between the time items are pushed and received but as far as I can tell it is, I tested it by adding a counter in to observable and printed the counter in the observer.</p>
  
  <p>I think that I'm missing something.</p>