aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/xyz/brysonsteck/serverfordummies/Download.kt
blob: b98b5111685b034a830d462391aabd42052d187f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import java.io.*;
import java.net.*;
import java.util.*;

class Download: Runnable {
  public enum class Status {
    DOWNLOADING, PAUSED, COMPLETE, CANCELLED, ERROR
  }
  public var size: Int
  public var downloaded: Int
  public var contentLength: Int
  public var status: Status

  private final val MAX_BUFFER_SIZE: Number = 1024

  private var url: URL
  private var dir: String

  constructor (url: URL, dir: String) {
    this.url = url
    this.dir = dir
    size = -1
    downloaded = 0
    status = Status.DOWNLOADING
    contentLength = 1
  }

  public fun start() {
    val thread = Thread(this)
    thread.start()
  }

  private fun getFilename(url: URL): String {
    val filename = url.getFile()
    return filename.substring(filename.lastIndexOf('/') + 1)
  }

  override fun run() { 
    var stream: InputStream? = null
    var file: RandomAccessFile? = null

    try {
      // Open connection to URL.
      var connection = url.openConnection() as HttpURLConnection;

      // Specify what portion of file to download.
      connection.setRequestProperty("Range", "bytes=" + downloaded + "-");

      // Connect to server.
      connection.connect();

      // Make sure response code is in the 200 range.
      if (connection.responseCode / 100 != 2) {
        status = Status.ERROR
      }

      // Check for valid content length.
      contentLength = connection.getContentLength();
      if (contentLength < 1) {
        status = Status.ERROR
      }

      /* Set the size for this download if it
        hasn't been already set. */
      if (size == -1) {
        size = contentLength;
      }

      // Open file and seek to the end of it.
      file = RandomAccessFile(dir + getFilename(url), "rw");
      file.seek(downloaded.toLong());

      stream = connection.getInputStream();
      while (status == Status.DOWNLOADING) {
        /* Size buffer according to how much of the
          file is left to download. */
        val buffer: ByteArray;
        if (size - downloaded > MAX_BUFFER_SIZE as Int) {
          buffer = ByteArray(MAX_BUFFER_SIZE)
        } else {
          buffer = ByteArray(size - downloaded);
        }

        // Read from server into buffer.
        val read = stream.read(buffer);
        if (read == -1)
          break;

        // Write buffer to file.
        file.write(buffer, 0, read);
        downloaded += read;
      }

      /* Change status to complete if this point was
          reached because downloading has finished. */
      if (status == Status.DOWNLOADING) {
          status = Status.COMPLETE;
      }
    } catch (e: Exception) {
      status = Status.ERROR
    } finally {
        // Close file.
        if (file != null) {
            try {
                file.close();
            } catch (e: Exception) {}
        }

        // Close connection to server.
        if (stream != null) {
            try {
                stream.close();
            } catch (e: Exception) {}
        }
    }
  }
}