Как сделать функцию дозагрузки файла

167
19 января 2019, 14:10

Скачиваю файл таким образом:

Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    trustAllHosts();
                    URL url = new URL(downloadUrl);//Create Download URl
                    HttpsURLConnection c = (HttpsURLConnection) url.openConnection();//Open Url Connection
                    //c.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
                    //c.setInstanceFollowRedirects(true);
                    c.setRequestMethod("GET");//Set Request Method to "GET" since we are grtting data
                    c.connect();//connect the URL Connection
                    //If Connection response is not OK then show Logs
                    if (c.getResponseCode() != HttpsURLConnection.HTTP_OK) {
                        Log.e(Constants.LOG_TAG, "Server returned HTTP " + c.getResponseCode() + " " + c.getResponseMessage());
                        return;
                    }
                    int fileSize = c.getContentLength();
                    int downloadSize = 0;
                    //If File is not present create directory
                    if (!toPath.exists()) {
                        toPath.mkdir();
                        Log.e(Constants.LOG_TAG, "Directory Created.");
                    }
                    File outputFile = new File(toPath, toFileName);//Create Output file in Main File
                    //Create New File if not present
                    if (!outputFile.exists()) {
                        if (outputFile.createNewFile())
                            Log.e(Constants.LOG_TAG, "File Created ");
                        else
                            Log.e(Constants.LOG_TAG, "File no Created ");
                    }
                    FileOutputStream fos = new FileOutputStream(outputFile);//Get OutputStream for NewFile Location
                    InputStream is = c.getInputStream();//Get InputStream for connection
                    byte[] buffer = new byte[1024];//Set buffer type
                    int len1 = 0;//init length
                    while ((len1 = is.read(buffer)) != -1) {
                        if (Thread.currentThread().isInterrupted()){
                            Log.d(Constants.LOG_TAG, "Загрузка файла прервано- " + outputFile.getPath());
                            fos.close();
                            is.close();
                            return;
                        }
                        fos.write(buffer, 0, len1);//Write new file
                        downloadSize+=len1;
                        int percent = (int) (downloadSize * 100 / fileSize);
                        updateUI(outputFile.getName(), fileSize, downloadSize);
                        Log.d(Constants.LOG_TAG, "Скачано " + percent + "%");
                    }
                    Log.d(Constants.LOG_TAG, "файл скачан " + outputFile.getPath());
                    //Close all connection after doing task
                    fos.close();
                    is.close();
                } catch (Exception e){
                    if (e instanceof InterruptedIOException || e instanceof InterruptedException){
                        if (downloadThreadMap.containsKey(downloadUrl)) {
                            downloadThreadMap.get(downloadUrl).interrupt();
                        }
                    }
                    e.printStackTrace();
                } finally {
                    if (downloadThreadMap.containsKey(downloadUrl)) downloadThreadMap.remove(downloadUrl);
                }
            }
        });
        downloadThreadMap.put(downloadUrl, thread);
        thread.start();

Возможно ли сделать дозагрузку файла например: при экстренной перезагрузки устройства.

Ссылка постоянная и прямая

Answer 1

Я не знаю всех нюансов, но в решении задачи Вам может помочь:

Поток в режиме дозаписи файла: new FileOutputStream(outputFile, true);

Если сервер поддерживает дозагрузку, то скорее всего он должен понимать заголовок "Range" и брать из него позиции:
connection.setRequestProperty("Range", "bytes=" + outputFile.length() + "-");

Для возобновления после перезагрузки нужен ресивер на android.intent.action.BOOT_COMPLETED и "запомнить" что у нас загружается (подробности можно найти в примерах и вопросах по будильникам/AlarmManager)

Answer 2

Честно говоря я не профессионал в области мобильной разработки, но мне кажется что рассуждаю почти правильно. Вся суть не в том какую функцию вы напишите, весь прикол в файле и работе с ним. Дозагрузка в том виде про который вы говорите довольно громоздкая, и требует много времени чтобы быть доведенной до ума.

Суть в чем: у вас на сервере есть файлик, вы его грузите сразу весь полностью одним так скажем куском. А для того чтобы у вас получилась дозагрузка вам нужно я думаю сделать так: раздробить ваш файл на несколько частей, и дальше при загрузке качать эти части на телефон, а на телефоне уже лепить все вместе.

Дальше например у вас возникла ситуация, когда загрузка неожиданно прерывается, можно и не только перезагрузкой прибить приложение, например ошибка возникла и приложение закрылось, система закрывает ваше приложение из-за недостатка ресурсов, другое приложение повлияло на его работу, и как результат у вас загрузка прервалась. Когда загрузка прерывается вам необходимо сохранить часть какую вы уже загрузили на устройстве, и дальше для "дозагрузки" обращаться к серверу за той частью которая идет сразу после загруженной, и после того как вы все части загрузили вам нужно через еще одну функцию все слепить вместе.

Честно говоря задача довольно интересная, но нужно учитывать очень много факторов, например вам лучше бы как-то сделать учет частей файла, чтобы при старте загрузки вам сервер кидал кол-во частей, и дальше вы уже делали учет их при загрузке. Так же вам нужно будет придерживаться четкой последовательности частей, чтобы файл после слепливания соответствовал тому что на сервере.

В целом вам нужно поработать с сервером и с файлом перед тем как создавать функцию дозагрузки, это значит подробить файл и прописать на сервере чтобы слались части вашего файла в четкой последовательности.

Надеюсь я вам помог в решении вашей задачи, если что-то будет не понятно, то я постараюсь объяснить.

READ ALSO
Проверка вводимого знака через консоль

Проверка вводимого знака через консоль

Пытаюсь писать свою малюсенькую программу и одна из основ - это написание метода, в котором пользователь делает выбор в меню с помощью вводы...

151
Будильник на Android

Будильник на Android

Разрабатываю будильник для ознакомления со сферой разработки для AndroidПроблема в следующем: не работает будильник

200
static nested class? [дубликат]

static nested class? [дубликат]

На данный вопрос уже ответили:

177