I'a using a asynctask to download file. It works normally until i turn off wifi connection (there are no other internet connection) of my android, download dialog still and no changes. When i check by log, i discover that function read() of inputstream is non stop. So how to check this case? here is my code:
URL url = new URL(this.url);
URLConnection connection = url.openConnection();
connection.setReadTimeout(1000);
connection.connect();
// this will be useful so that you can show a typical 0-100% progress bar
int fileLength = connection.getContentLength();
fileName = "temp.zip";
// download the file
InputStream input = new BufferedInputStream(connection.getInputStream());
OutputStream output = new FileOutputStream(path+fileName);
byte buffer[] = new byte[1024000];
long total = 0;
int count;
Log.v("test download:","download in background");
while (((count = input.read(buffer)) != -1)) {
Log.v("test download:","read:"+count);
total += count;
publishProgress((int) (total * 100 / fileLength - 1));
output.write(buffer, 0, count);
}
Since you already set a timeout by calling setReadTimeout(), you should get a SocketTimeoutException shortly after the connection dropped.
Do your code happen to maybe capture this exception silently?
Your file download buffer size is too much byte buffer[] = new byte[1024]; is enough
when i try this Download a file with Android, and showing the progress in a ProgressDialog (top answer) with asynctask ,work fine, didn't get that problem
Related
In my android application I am downloading large files from server(1GB) using the following:
connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setReadTimeout(7000);
connection.connect();
input = connection.getInputStream();
output = new FileOutputStream("/sdcard/Android/" + fileName, true);
byte data[] = new byte[1024];
int count;
int total = 0;
while (count = input.read(data)) > 0) {
total = total + count;
output.write(data, 0, count);
}
The code works well. But sometimes the downloaded file gets corrupted and I don't know why! Is there a mechanism or algorithm, library ... to guarantee a successful download 100%? Please help, I don't know what to do! I don't want to use checksum to check if the file is ok and if not then download it again! I want a solution to detect the problem while downloading and fix the corrupted portion instantly!
I am using the below code to download zip file in android.code works fine ,but sometimes download fails and throws socket exception. especially while Internet connection is slow(i guess).i have also posted the screen shots of logcat error message.
int count;
URL url = new URL(URL);
URLConnection conexion = url.openConnection();
conexion.connect();
int lenghtOfFile = conexion.getContentLength();
//Log.e("ANDRO_ASYNC", "Lenght of file: " + "="+lenghtOfFile);
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(StorezipFileLocation);
byte data[] = new byte[lenghtOfFile];
long total = 0;
while ((count = input.read(data)) != -1) {
total += c![enter image description here][1]ount;
publishProgress(""+(int)((total*100)/lenghtOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
connection reset by peer usually means that you are talking to a peer wich think that the connection has already been closed. What I don't understand is why it happens when closing a FileOutputStream.
Besides, the exception does not happen in your code but in the finalizer. Is it possible that when something goes wrong, you catch the exception in an upper level and leave the connection and file opened ? The abandonned connection is closed by the finalyser, but it's too late.
I am not sure that it will solves the problem but it is a good practice to use a finally clause to be sure that files and connections are properly closed.
The log doesn't say where the crash occurs in your code. Isn't there some more info that doesn't appear in your screenshot?
It seems that it fails on the close method of your file input stream.
You could simply surround the calls to close() with a try catch block and set your stream to null (if it failed on closing)
I have a URL which, when I enter in browser, opens the image perfectly. But when I try the following code, I get getContentLength() as -1:
URL url = new URL(imageUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// determine the image size and allocate a buffer
int fileSize = connection.getContentLength();
Please guide me what can be the reason behind this?
If the server is sending down the response using Chunked Transfer Encoding, you will not be able to pre-calculate the size. The response is streamed, and you'll just have to allocate a buffer to store the image until the stream is complete. Note that you should only do this if you can guarantee that the image is small enough to fit into memory. Streaming the response to flash storage is a pretty reasonable option if the image may be large.
In-memory solution:
private static final int READ_SIZE = 16384;
byte[] imageBuf;
if (-1 == contentLength) {
byte[] buf = new byte[READ_SIZE];
int bufferLeft = buf.length;
int offset = 0;
int result = 0;
outer: do {
while (bufferLeft > 0) {
result = is.read(buf, offset, bufferLeft);
if (result < 0) {
// we're done
break outer;
}
offset += result;
bufferLeft -= result;
}
// resize
bufferLeft = READ_SIZE;
int newSize = buf.length + READ_SIZE;
byte[] newBuf = new byte[newSize];
System.arraycopy(buf, 0, newBuf, 0, buf.length);
buf = newBuf;
} while (true);
imageBuf = new byte[offset];
System.arraycopy(buf, 0, imageBuf, 0, offset);
} else { // download using the simple method
In theory, if the Http client presents itself as HTTP 1.0, most servers will switch back to non-streaming mode, but I don't believe this is a possibility for URLConnection.
I am late here but this might help someone. I was facing same issue i was always getting -1 value, when ever i was trying get the content length.
previously i was using below method to get content length.
long totalByte=connection.getContentLength();
Below fixed my problem:-
long totalByte=connection.getHeaderFieldLong("Content-Length",-1);
Is there any way in android API 7+ that I can report on the progress of a call to HttpEntity.getContent()?
In my case I am getting an image in the response stream so the transfer can take quite a while. I want to have a ProgressDialog with the style set to STYLE_HORIZONTAL be updated with the progress of the transfer.
Any way to do this?
Thanks!
Have you tried HttpEntity.getContentLength() to help you predetermine the size of the file? If you use that in conjunction with something like AsyncTask's onProgressUpdate(), you should be able to implement that.
Take a look at this link
Download a file with Android, and showing the progress in a ProgressDialog
It has pretty much what you're looking for. it uses urlConnection to get the InputStream so you would need to adapt that to use HttpEntity. So maybe you'd have something like this.
#Override
protected String doInBackground(String... aurl) {
int count;
long contentLength = <yourHttpEntity>.getContentLength();
InputStream input = new BufferedInputStream(<yourHttpEntity>.getContent());
OutputStream output = new FileOutputStream("/sdcard/your_photo.jpg");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress(""+(int)((total*100)/contentLength));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
}
and update your dialog in onProgressUpdate.
I am downloading on my android app. I am using a local network connection and the download is really slow.
Here's he code I am using:
URL url = new URL(ep.getFileURL());
File destFile = new File(<path to sd card file>);
URLConnection uCon = url.openConnection();
InputStream is = uCon.getInputStream();
OutputStream os = new FileOutputStream(destFile);
int progress = 0;
int lastProgress = 0;
int totalSize = uCon.getContentLength();
int downloadedSize = 0;
byte[] buffer = new byte[4096];
int count = -1;
while((count = is.read(buffer)) != -1)
{
os.write(buffer, 0, count);
downloadedSize = downloadedSize + count;
progress = (int)(downloadedSize * 100.0 / totalSize);
if(progress - lastProgress >= 5) {
publishProgress(progress);
lastProgress = progress;
}
}
os.close();
Do you spot any problems? thank you.
Edit:
I tested my code using your suggestions and I got these results:
# Download times tests #
Without bufferedoutput
Downloading file: 1 ms, Start download
Downloading file: 179812 ms, Finished downloading 54687744 bytes
Downloading file: end, 179813 ms
With bufferedoutput
Downloading file: 1 ms, Start download
Downloading file: 178312 ms, Finished downloading 54687744 bytes
Downloading file: end, 178313 ms
With httpclient
Downloading file: begin
Downloading file: 1 ms, Start download
Downloading file: 178241 ms, Finished downloading 54687744 bytes
Downloading file: end, 178242 ms
So, using Buffered streams or using HttpClient directly, doesn't change anything...
I also should have mentioned that my code is inside a AsyncTask, so publishProgress() actually runs on a separated thread already...
Thank you for your help.
You should wrap your input stream with a BufferedInputStream. You're probably getting a lot more shallow reads of a few bytes and a buffered stream will alleviate some of that. I would try that first, buffering both the input and output streams to reduce the OS level write delays.
Second, I'd be careful with how you are posting progress. It looks like you are limiting the number of times it comes up, but you might want to move the download into its own runnable and use an executor service for the download and maybe start an additional thread which evaluates the progress of all downloads and fires progress messages as necessary.
Use HttpClient instead of URLConnection