开发者

Android:"Unexpected end of stream" exception downloading large files

开发者 https://www.devze.com 2023-04-04 08:19 出处:网络
I am building an Android Application and I need to download a file from a url, which is 33 MB large. Here the download task:

I am building an Android Application and I need to download a file from a url, which is 33 MB large.

Here the download task:

try {
            int MAX_BUFFER_SIZE = 4096;
            URL mUrl = new URL(params[0]);
            HttpURLConnection connection = (HttpURLConnection) mUrl.openConnection();
            connection.setRequestMethod("GET");
            long length = connection.getContentLength(), downloaded = 0;
            int read;
            byte [] buffer = new byte[(((int)length) > MAX_BUFFER_SIZE) ? MAX_BUFFER_SIZE : (int)length];
            String filename = getFilename(mUrl);
            File file = new File (SDCARD_ROOT);
            if (!file.exists() || !file.isDirectory()){
                file.mkdir();
            }
            this.filename = filename;
            file = new File (SDCARD_ROOT + this.filename);  
            FileOutputStream fos = new FileOutputStream (file);
            //Start downloading
            InputStream stream = connection.getInputStream();

            while ((read=stream.read(buffer)) > -1){
                fos.write(buffer, 0, read);
                downloade开发者_JAVA百科d += read;
                publishProgress((int) ((float) downloaded/length * 100));
            }
            fos.close();
            return 1;
        } catch (Exception e){
            Log.e("REV-PARTS", "Revolver parts error in DownloadTask: " + e.getMessage());  
            return 2;
        }

It works right with small files (1-15 MB), but it will return a "unexpected end of stream" exception with large files.


Setting a chunk size seemed to work for me.

connection.setChunkedStreamingMode(1048576);


For large files you need to set the connection time out manually by using the following code. I have set the time out to 3 minutes

   connection.setConnectTimeout(180000);
   connection.setReadTimeout(180000);


While you catch the exception, I try the method downContinue(). I can show my code:

private void downloadApk() {
    thread1 = new Thread() {
        public void run() {
            File oFile = null;
            try {
                URL url = new URL(PQGLApplication.resrootURL + "apk/PQGLMap.apk");
                HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                ReadableByteChannel channel =
                        Channels.newChannel(urlConnection.getInputStream());
                oFile =
                        new File(Environment.getExternalStorageDirectory().getAbsolutePath()
                                + "/" + "hy_ht_new/" + "test2" + ".apk");
                oFile.setWritable(true);
                oFile.setReadable(true);
                if (oFile.exists()) {
                    oFile.delete();
                }
                FileOutputStream fos = new FileOutputStream(oFile);
                fileSize = urlConnection.getContentLength();
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                int noOfBytes = 0;
                byte[] data = null;
                sendApkMessage(0, 0);
                while ((noOfBytes = channel.read(buffer)) > 0) {
                    data = new byte[noOfBytes];
                    System.arraycopy(buffer.array(), 0, data, 0, noOfBytes);
                    buffer.clear();
                    fos.write(data, 0, noOfBytes);
                    downLoadFileSize += noOfBytes;
                    sendApkMessage(1, downLoadFileSize);
                }
                fos.flush();
                fos.close();
                channel.close();
                sendApkMessage(2, oFile.getAbsolutePath());
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                downContinue();
            }
        };
    };
    thread1.start();
}

private void downContinue() {
    continueTime++;
    try {
        if (continueTime == 3) {
            continueTime = 0;
            sendApkMessage(4, 0);
            Log.e("what is the continuetime", "continueTime" + continueTime);
        } else {
            URL url = new URL(PQGLApplication.resrootURL + "apk/PQGLMap.apk");
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            File oFile =
                    new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/"
                            + "hy_ht_new/" + "test2" + ".apk");
            RandomAccessFile oSavedFile = new RandomAccessFile(oFile, "rw");
            FileOutputStream fos = new FileOutputStream(oFile);
            ReadableByteChannel channel = Channels.newChannel(urlConnection.getInputStream());
            // oSavedFile.seek(nPos);
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            byte[] data = null;
            int temp = 0;
            sendApkMessage(3, oFile.getAbsolutePath());
            while ((temp = channel.read(buffer)) > 0) {
                data = new byte[temp];
                System.arraycopy(buffer.array(), 0, data, 0, temp);
                buffer.clear();
                fos.write(data, 0, temp);
            }
            fos.flush();
            fos.close();
            oSavedFile.close();
            sendApkMessage(2, oFile.getAbsolutePath());
            continueTime = 0;
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        Log.e("what is the exception", e.toString() + continueTime);
        downContinue();
    }

}

This downContinue method is used to solve this problem. At least, the file is downloaded successfully!

0

精彩评论

暂无评论...
验证码 换一张
取 消