I am trying to download a PPT file from a server.
it's in Bytes.
but while debugging I noticed that the input stream throws an exception of FileNotFound while running.. the file does exist on the server, here's my code, any help would be greatly appreciated.
public class DownloadFileAsync extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... aurl) {
int count;
try {
URL url = new URL(aurl[0]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.addRequestProperty("Authorization", "Basic " + SharedPref.getAuthPrefValue());
connection.addRequestProperty("Device", BaseApplication.getCurrentDevice().getDevice().toString());
connection.addRequestProperty("DeviceId", BaseApplication.getCurrentDevice().getDeviceId());
connection.connect();
int lengthOfFile = connection.getContentLength();
Log.d("ANDRO_ASYNC", "Length of file: " + lengthOfFile);
InputStream input = new BufferedInputStream(url.openStream());
File sdcardDest = new File(Environment.getExternalStorageDirectory(), "Availo");
String finalDest = sdcardDest + File.separator + "Check1" + "." + "PPT";
OutputStream output = new FileOutputStream(finalDest);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress(""+(int)((total*100)/lengthOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
I am using Charles on Mac (which is similar to fiddler on windows.) to see what I send and receive from the server,
The server doesn't return any error, though it shows download steps for 6-7 sec, downloading around 400 bytes and then it stops.
The Exception is thrown from the input stream line.
Thanks!
I suggest you take a look at the DownloadManager system service. it's designed specifically for what you are trying to do:
(from the documentation)
The download manager is a system service that handles long-running
HTTP downloads. Clients may request that a URI be downloaded to a
particular destination file. The download manager will conduct the
download in the background, taking care of HTTP interactions and
retrying downloads after failures or across connectivity changes and
system reboots
While I do agree with Muzikant regarding the download manager,
FileNotFoundException is usually thrown when... the file is not found on the local device...
You need to do the following to make sure it doesnt happen
File dest = new File(finalDest);
try{
File parentDest = dest.getParentFile();
if(!parentDest.exists()){
parentDest.mkdirs(); //make all the directory structures needed
}
if(!dest.exists()){
dest.createNewFile();
}
OutputStream output = new FileOutputStream(dest);
//now you can use your file dest
//write data to it...
}catch (Exception e){
}
Related
I'm trying to convert this image url to file object :
https://graph.facebook.com/v4.0/10211842143528384/picture?height=200&width=200&migration_overrides=%7Boctober_2012%3Atrue%7D
this link came from the facebook response after i logged in.
i used this method to convert this image url to File object:
URL url = null;
try {
url = new URL(sharePreferences.getPreferencesProfilePicture());
} catch (MalformedURLException e) {
e.printStackTrace();
}
File f = new File(url.getFile());
Log.d("CHECKER",""+f.exists());
Log.d("CHECKER",""+f.length());
but when i check it's length, its just 0 and the file exist is false.
You have a file with length 0 because you are just creating it with the name of the result of url.getFile(), url.getFile() returns a string which corresponds to the fetched file name.So you end up with a file named picture:
https://graph.facebook.com/v4.0/10211842143528384/picture?height=200&width=200&migration_overrides=%7Boctober_2012%3Atrue%7 But what about the contents? you have to download them fron the internet as a stream and feed that stream into a file. There many ways of doing that with plain Java. A basic copy-paste from https://www.baeldung.com/java-download-file
try (BufferedInputStream in = new BufferedInputStream(new URL(FILE_URL).openStream());
FileOutputStream fileOutputStream new FileOutputStream(FILE_NAME)) {
byte dataBuffer[] = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
fileOutputStream.write(dataBuffer, 0, bytesRead);
}
} catch (IOException e) {
// handle exception
}
Since you are using android I would strongly encourage you to use fully featured Network libraries such as OkHttp3, Retrofit or Volley, but guessing your knowledge I think you will do better learning the basics on Java then jump to the mentioned libraries.
Remember, for android you need the INTERNET permission to access the internet, then if you download into a file on the external storage you would also need the EXTERNAL_STORAGE permission. Snippet for android:
try {
URLConnection conection = url.openConnection();
conection.connect();
int lenghtOfFile = conection.getContentLength();
// Read from the Network stream
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(Environment
.getExternalStorageDirectory().toString()
+ "/downloaded.png");
byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
total += count;
// Feed the bytes read from the input stream into our output stream
output.write(data, 0, count);
}
// Flushing the out stream.
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
This snippet does networking stuff so you need to run it on a background thread. I hope my answer helps you, if not, let me know what else can I do for you.
I want to download all the images I have on server in the array string of Url one by one so that I may do not have to download a zip file of images from the server and to unzip after downloading it.
So I thought to download the images one by one and to show the download status in the progress bar. But I am extremely failed in it. An Idea came into my mind to make the string array of the Url and to use the For loop to download but it is downloading the last image of the String array and decline or pass all other images in the array . I think I have got the idea that what is going on but I have know Idea what would be the solution then.
What I have done So far
protected Void doInBackground(Void... arg0) {
try {
//set the download URL, a url that points to a file on the internet
//this is the file to be downloaded
String [] imageUrl = {"http://www.androidbegin.com/tutorial/flag/india.png","http://www.androidbegin.com/tutorial/flag/pakistan.png"
,"http://www.androidbegin.com/tutorial/flag/china.png","http://www.androidbegin.com/tutorial/flag/unitedstates.png"};
URL url;
HttpURLConnection urlConnection = null;
for(int i=0;i<imageUrl.length;i++){
url = new URL(imageUrl[i]);
//create the new connection
urlConnection = (HttpURLConnection) url.openConnection();
//set up some things on the connection
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
//and connect!
urlConnection.connect();
}
File storagePath = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "Test");
storagePath.mkdirs();
String finalName = Long.toString(System.currentTimeMillis());
File myImage = new File(storagePath, finalName + ".png");
//this will be used to write the downloaded data into the file we created
FileOutputStream fileOutput = new FileOutputStream(myImage);
//this will be used in reading the data from the internet
InputStream inputStream = urlConnection.getInputStream();
//this is the total size of the file
int totalSize = urlConnection.getContentLength();
//variable to store total downloaded bytes
int downloadedSize = 0;
//create a buffer...
byte[] buffer = new byte[1024];
int bufferLength = 0; //used to store a temporary size of the buffer
//now, read through the input buffer and write the contents to the file
while ((bufferLength = inputStream.read(buffer)) > 0) {
//add the data in the buffer to the file in the file output stream (the file on the sd card
fileOutput.write(buffer, 0, bufferLength);
//add up the size so we know how much is downloaded
downloadedSize += bufferLength;
//this is where you would do something to report the prgress, like this maybe
// updateProgress(downloadedSize, totalSize);
}
//close the output stream when done
fileOutput.close();
//catch some possible errors...
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// see http://androidsnippets.com/download-an-http-file-to-sdcard-with-progress-notification
return null;
}
** What I want :**
Download all the images one by one.
After downloading one Image it should get save in the device and update the progress status.
Please show me some source code rather then giving me just Idea how to do it. And little source code and complete work around on this would be appreciated.
the saving image code should be taken inside for loop. as this code is outside of for loop only your last image is getting saved as at the end of for loop last url is used.
working on my first real android app and one part of it is a download manager.
it must download video files that the app uses to teach people Gaelic.
it works fine on all but 3 files, it downloads bigger files and smaller files. but will not download colours.mp4 1.86MB, weekdays 1.53 MB or numbers 1.99 MB all the files between 1MB and 2MB.
it will just stop at the end of the download loop no errors for a few minutes just looking like its waiting to continue downloading then it will give an error "unexpected end of stream"
can anyone suggest what the problem could be please?
I have crated the same app for the iPhone and that app has not got the same problem with these files.
this is the download loop called from inside an asynctask.
protected void download(String where, String file){
try {
//makes output file
OutputStream output = new FileOutputStream(getFilesDir()
.getAbsolutePath() + "/vidos/" +file);
int count=0;
//gets url to download from
URL url = new URL(where);
URLConnection conection = url.openConnection();
conection.connect();
//gets the length of the file to work out percent downloaded
int lengthOfFile = conection.getContentLength();
InputStream input = null;
Log.v("downloading", String.valueOf(showprg));
input = new BufferedInputStream(url.openStream());
byte data[] = new byte[lengthOfFile];
long total = 0;
Log.v("downloading", "size: " + String.valueOf(downloading));
while ((count = input.read(data)) > 0 && downloading) {
total += count;
publishProgress(String
.valueOf((int) ((total * 100) / lengthOfFile)));
output.write(data, 0, count);
//this is where it brakes
};
Log.v("publishProgress", "done");
output.flush();
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
}
I changed my URLConnection to a HttpURLConnection and removed the BufferedInputStream and now it downloads without problem.
thanks to Harshit Rathi for his link to Cristian's post
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Android:“Unexpected end of stream” exception downloading large files
I'm downloading a file with the following code below. The file is approx. 5MB in size. However, I'm getting a java.io.IOException "unexpected end of stream" error when the download is around 60-90%
I don't understand how to solve it and it's driving me crazy.
EDIT: Could someone at least just test it, if it downloads a file successfully on your phone. This will allow me to determine whether the problem is my phone or the code.
try {
URL url = new URL(full_url);
conexion = (URLConnection)url.openConnection();
conexion.setReadTimeout(20000);
conexion.connect();
File file = new File(root.getAbsolutePath()+"/", fileName);
int lenghtOfFile = conexion.getContentLength();
System.out.println("content-length-header is: " + lenghtOfFile);
InputStream input = conexion.getInputStream();
OutputStream output = new FileOutputStream(file);
byte data[] = new byte[8192];
long total = 0;
contentView.setTextViewText(R.id.status_text,"Downloading file " + (78 - GlobalData.missingFiles.size()) + " of " + 77);
int downloadProgress = (int)((total*100)/lenghtOfFile);
int lastProgressUpdate=0;
while ((count = input.read(data)) != -1) {
System.out.println("available bytes:" + input.available());
total += count;
downloadProgress = (int)((total*100)/lenghtOfFile);
Log.e("totaltotal","" + (int)((total*100)/lenghtOfFile));
output.write(data,0,count);
if(downloadProgress%20==0 && downloadProgress != lastProgressUpdate) {
notification.contentView.setProgressBar(R.id.status_progress, 100,downloadProgress, false);
notificationManager.notify(1,notification);
lastProgressUpdate=downloadProgress;
}
if(downloadProgress == 100){
GlobalData.downloadFiles.add("" +fileName);
GlobalData.missingFiles.remove(fileName);
}
}
output.flush();
output.close();
input.close();
if(downloadProgress != 100){
File temp_file = new File(root.getAbsolutePath()+"/", fileName);
try{
if(temp_file.exists()){
boolean del_main = temp_file.delete();
Log.e("File","Does file exists: " + del_main);
Log.e("FilePath","PATH: " + temp_file.getAbsolutePath());
}else{
Log.e("File Exists NOT","NOT EXISTING");
}
}catch(Exception e){
Log.e("FileDelete","deleting is giving problems");
}
}
} catch (Exception e) {
Log.e("PRINTSTACK","STACK:" + e.getMessage());
e.printStackTrace();
System.out.println("Downloading didn't work");
killService();
}
For some reason the input stream is closing prematurely. Often this is since an inputstream is read mulitple times at once, but I'm guessing this is not the case here, even though you for some reason have conexion available in a wider scope than we see here.
You say conexion = (URLConnection)url.openConnection(); instead of the expected URLConnection conexion = url.openConnection();. Please make sure you do not try to fetch the input stream twice.
The only other thing I can see that is weird when I look is that you use the inputstream from conexion.getInputStream() directly. Try wrapping it in a buffered input stream as such:
InputStream input = new BufferedInputStream(connexion.getInputStream());
I have this snippet of code in which I want to handle the downlaod of the file being clicked:
else if (url.startsWith("http://rapahh.com/songs2/Music%20Promotion/Download/")) {
}
return false;
Although I have no idea how to handle downloads in Android, so does anyone have a snippet of code I can use to download the file in the background to a folder.. the download folder is fine. Thanks.
What version of android are you building for?
Starting with API lvl 9 there is the DownloadManager that can handle this for you. If at all possible you should use the DownloadManager, because it will automatically handle network interuptions and resume the downloads for you.
If you are aiming for lower API lvl than that you'll have to make the download code yourself. You'll have an inputStream coming from your web source and an outputStream going to your local file and you will loop through the inputStream writing chunks until there are none left.
Something like this:
try {
URL url = new URL(URL); //URL of the video
//Set our file to the correct path and name.
File file = new File(PATH + fileName);
//keep the start time so we can display how long it took to the Log.
long startTime = System.currentTimeMillis();
Log.d(myTag, "download begining");
//Log.d(myTag, "download url:" + url);
Log.d(myTag, "downloaded file name:" + fileName);
/* Open a connection to that URL. */
URLConnection ucon = url.openConnection();
// this will be useful so that you can show a tipical 0-100% progress bar
int lenghtOfFile = ucon.getContentLength();
Log.i(myTag, "Opened Connection");
/************************************************
* Define InputStreams to read from the URLConnection.
************************************************/
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
Log.i(myTag, "Got InputStream and BufferedInputStream");
/************************************************
* Define OutputStreams to write to our file.
************************************************/
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
Log.i(myTag, "Got FileOutputStream and BufferedOutputStream");
/************************************************
* Start reading the and writing our file.
************************************************/
byte data[] = new byte[1024];
long total = 0;
int count;
//loop and read the current chunk
while ((count = bis.read(data)) != -1) {
//Post our progress update back to the UI thread
postProgress((int)(total*100/lenghtOfFile));
//write this chunk
total += count;
bos.write(data, 0, count);
}
//Have to call flush or the video file can get corrupted and won't play correctly.
bos.flush();
bos.close();
Log.d(myTag, "download ready in "
+ ((System.currentTimeMillis() - startTime))
+ " milisec");
} catch (IOException e) {
Log.d(myTag, "Error: " + e);
}
You'll need to implement the postProgress(int progress) method to do whatever is appropriate for your application to inform the user of what percentage complete the download is.
Edit:
you can comment out the logs to get it to work. I leave them on while I am debugging though to make the process easier. Log statements such as Log.i(String tag, String text)
are similar to System.out.println(String txt) The difference is that these statements are printed into the log file ( which you can see in the DDMS perspective in eclipse) And they have an additional parameter called "tag" you can pass it whatever string you like and this string will show up along side of your text in the log file. You can also filter the log output basted on these tags in the DDMS perspective. It is common practice to declare your tag as a static String so that you can just use that reference to it for all of your log statements and you are guaranteed to always have the same tag. So if you add something like this to your class it should fix your error:
final static String myTag = "NameOfYourActivity";