InputStream возвращает пустой файл при загрузке PDF

Итак, я пытаюсь загрузить файл PDF с помощью HttpURLConnection, и я думаю, что все сделал правильно с входными и выходными потоками, но когда я открываю загруженный файл PDF (используя встроенный файловый менеджер в Android и/или ADB) , или просто проверить его, передав в OS X, он совершенно пустой и размер показывает 0 байт.

Сайт, с которого я пытаюсь загрузить PDF:

http://www.pdf995.com/samples/pdf.pdf< /под>

Вот мой код

    public static void DownloadFile(final String fileURL, final File directory) {

    Thread thread = new Thread(new Runnable(){
        @Override
        public void run() {
            try {

                try {
                    FileOutputStream f = new FileOutputStream(directory);
                    URL u = new URL(fileURL);
                    c = (HttpURLConnection) u.openConnection();
                    c.setRequestMethod("GET");
                    //c.setRequestProperty("Content-Type", "application/pdf");
                    //c.setDoOutput(true);
                    c.connect();
                    Log.d("debugz", Integer.toString(c.getContentLength()));

                    InputStream in = c.getInputStream();

                    byte[] buffer = new byte[1024];
                    int len1 = 0;
                    while ((len1 = in.read(buffer)) > 0) {
                        f.write(buffer, 0, len1);
                    }
                    f.flush();
                    f.getFD().sync();
                    f.close();


                } catch (Exception e) {
                    e.printStackTrace();
                }


            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });

    thread.start();


}


public static String getPDF(String pdfurl) {

    String extStorageDirectory = Environment.getExternalStorageDirectory()
            .toString();
    File folder = new File(extStorageDirectory, "schematisktscheman");
    folder.mkdir();
    File file = new File(folder, "schemainfo.pdf");
    try {
        file.createNewFile();
    } catch (IOException e1) {
        e1.printStackTrace();
    }
    DownloadFile(pdfurl, file);

    return null; //added return
}

В моей основной деятельности:

SchedulePdfProcessor.getPDF("http://www.pdf995.com/samples/pdf.pdf");
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + Environment.getExternalStorageDirectory() + "/schematisktscheman/schemainfo.pdf")));

РЕДАКТИРОВАТЬ: я запустил сетевой код в основном потоке, что вызвало исключение. Теперь создайте новый поток для загрузки, и он получит пример PDF (http://www.pdf995.com/samples/pdf.pdf) и отлично помещает его содержимое в файл. Спасибо @greenapps!


person Zino    schedule 27.02.2016    source источник
comment
тем не менее, когда я открываю загруженный PDF-файл или просто просматриваю его, он совершенно пуст, а размер показывает 0 байт - как точно вы это делаете? Используете ли вы настольную ОС с устройством, которое монтируется как диск или том? Используете ли вы какой-нибудь файловый менеджер на устройстве? Вы используете что-то другое?   -  person CommonsWare    schedule 28.02.2016
comment
Я сохраняю файл на свое устройство Android, а затем просматриваю файл с помощью файлового менеджера в ОС. Код работает в приложении.   -  person Zino    schedule 28.02.2016
comment
Попробуйте изменить условие цикла на (len1 = in.read(buffer)) != -1   -  person cketti    schedule 28.02.2016
comment
@cketti Я пробовал, к сожалению, безрезультатно   -  person Zino    schedule 28.02.2016
comment
Oc.setRequestProperty("Content-Type", "application/pdf");. Удалите это. Вы не отправляете данные в формате PDF на сервер.   -  person greenapps    schedule 28.02.2016
comment
.setDoOutput(true);. Удалите это. Вы не делаете вывод.   -  person greenapps    schedule 28.02.2016
comment
Вместо того, чтобы удалять код здесь, вы можете прокомментировать эти операторы. Поскольку сейчас мои комментарии имеют мало смысла.   -  person greenapps    schedule 28.02.2016
comment
@greenapps Я сделал обе эти вещи, но PDF-файл все еще пуст. Спасибо, что объяснили, почему они тоже не помогают. Я добавил их обратно и вместо этого прокомментировал их, я подумал, что сводки по редактированию объяснят их, но, возможно, люди их не читают.   -  person Zino    schedule 28.02.2016
comment
GetPdf() не возвращает строку. И URL-адрес, который вы использовали, отличается от того, о котором вы говорили.   -  person greenapps    schedule 28.02.2016
comment
@greenapps Он возвращает строку в моем реальном коде, но в любом случае это не имеет значения для проблемы, поскольку методу просто нужно загрузить PDF-файл и вывести его во вновь созданный файл.   -  person Zino    schedule 28.02.2016
comment
Пустой файл загрузки(). Сделайте это логическим. И проверьте возвращаемое значение после использования. Поместите журналы в блоки catch, так как теперь вы не знаете, что происходит.   -  person greenapps    schedule 28.02.2016
comment
Все вопросы. И вы должны показать хороший код.   -  person greenapps    schedule 28.02.2016
comment
Глупо жестко кодировать нулевое возвращаемое значение для getPdf(). getPdf() должен вернуться, если все прошло нормально. Так что вы не будете звонить приемнику вещания, когда что-то пошло не так. Пожалуйста, напишите код получше, так как теперь вы не знаете, что и где происходит.   -  person greenapps    schedule 28.02.2016
comment
Это не место для болтовни.   -  person greenapps    schedule 28.02.2016
comment
file.createNewFile();. Удалите это заявление. Новый поток вывода файла создаст файл. Более того, даже если у вас есть улов, вы вызываете DownloadFile(), что является плохой практикой.   -  person greenapps    schedule 28.02.2016
comment
Весь плохой код является результатом того, что я раньше не работал с подключениями и отчаянно добавлял ненужный код, который мне не нужен, в надежде заставить его работать. Как вы думаете, запись c.getContentLength() поможет мне увидеть, есть ли какой-либо актуальный контент?   -  person Zino    schedule 28.02.2016
comment
Пожалуйста, не оскверняйте свои собственные сообщения, особенно после того, как люди приложили усилия, чтобы помочь и ответить. Если вы хотите, чтобы ваше имя было удалено из сообщения, отметьте его для внимания модератора и попросите отмежеваться.   -  person S.L. Barth    schedule 06.03.2016


Ответы (2)


Во-первых, заменить:

f.close();

с:

f.flush();
f.getFD().sync();
f.close();

Это гарантирует, что все будет записано на диск перед продолжением.

Затем вам нужно использовать MediaScannerConnection и scanFile(), чтобы MediaStore узнал об обновленном файле.

person CommonsWare    schedule 27.02.2016
comment
Вместо этого я избавился от исключения, используя это: Хотя файл все равно пустой - person Zino; 28.02.2016
comment
@Zino: Во-первых, вам нужно использовать scanFile() (или, возможно, эту трансляцию) после загрузки, а не до. Если это не помогает, используйте для проверки файла какой-либо другой инструмент (например, adb shell, файловый менеджер DDMS/Android Device Monitor, встроенный в устройство файловый менеджер). Если там пусто, то проблема где-то в вашем коде загрузки, хотя это выглядит нормально. - person CommonsWare; 28.02.2016
comment
Я сделал это сейчас, как вы можете видеть в моем обновленном вопросе, но проблема остается. - person Zino; 28.02.2016

Я запустил сетевой код в основном потоке, что вызвало исключение. Теперь создайте новый поток для загрузки, и он получит пример PDF (http://www.pdf995.com/samples/pdf.pdf) и отлично помещает его содержимое в файл.

Thread thread = new Thread(new Runnable(){
        @Override
        public void run() {
            try {

                try {
                    FileOutputStream f = new FileOutputStream(directory);
                    URL u = new URL(fileURL);
                    c = (HttpURLConnection) u.openConnection();
                    c.setRequestMethod("GET");
                    //c.setRequestProperty("Content-Type", "application/pdf");
                    //c.setDoOutput(true);
                    c.connect();
                    Log.d("debugz", Integer.toString(c.getContentLength()));

                    InputStream in = c.getInputStream();

                    byte[] buffer = new byte[1024];
                    int len1 = 0;
                    while ((len1 = in.read(buffer)) > 0) {
                        f.write(buffer, 0, len1);
                    }
                    f.flush();
                    f.getFD().sync();
                    f.close();


                } catch (Exception e) {
                    e.printStackTrace();
                }


            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });

    thread.start();
person Zino    schedule 28.02.2016
comment
ran the network code on the main thread, which threw an exception . Ты должен был сказать это сразу. И не «исключение», а NetworkOnMainThreadException. И что ваше приложение рухнуло. - person greenapps; 29.02.2016