How to handle empty space in url when downloading image from web? - android

I'm working on a project where the url sometimes can have empty spaces in it (not always) example: www.google.com/ example/test.jpg and sometimes www.google.com/example/test.jpg.
My code:
try {
URL url = new URL(stringURL);
URLConnection conexion = url.openConnection();
conexion.connect();
// downlod the file
InputStream input = new BufferedInputStream(url.openStream(), 8192);
OutputStream output = new FileOutputStream(fullPath.toString());
byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
e.printStackTrace();
}
It's this line that fails: InputStream input = new BufferedInputStream(url.openStream(), 8192);
with a: java.io.FileNotFoundException.
I've tryed to encode the specific line but here is the kicker: the server needs the empty space " " in order to find the file, so I need to have the empty space somehow. I can find the file (jpg) if i use firefox browser.
Any help much appreciated.
Edit update:
Well now I've tryed to encode every single bit after the host part of the url to utf-8 and I've tryed using both + and %20 for blank space. Now I can manage to DL the file but it will be faulty so it can't be read.
Edit update2:
I had made a mistake with %20, that works.

Okay I solved the headache.
First I use:
completeUrl.add(URLEncoder.encode(finalSeperated[i], "UTF-8"));
For every part of the url between "/"
Then I use:
ArrayList<String> completeUrlFix = new ArrayList<String>();
StringBuilder newUrl = new StringBuilder();
for(String string : completeUrl) {
if(string.contains("+")) {
String newString = string.replace("+", "%20");
completeUrlFix.add(newString);
} else {
completeUrlFix.add(string);
}
}
for(String string : completeUrlFix) {
newUrl.append(string);
}
To build a proper urlString.
The reason this works is because http needs %20. See Trouble Percent-Encoding Spaces in Java comment by Powerlord

Related

Image URL to File Object

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.

How to download the file with original extension from Firebase storage?

I'm trying to download files from Firebase storage. But when I download it, it's giving some files with .bin extension. But I want to get the original file name.
Here is my code.
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
int lenghtOfFile = conection.getContentLength();
InputStream input = new BufferedInputStream(url.openStream(),
8192);
OutputStream output = new FileOutputStream(Environment
.getExternalStorageDirectory().toString()
+"/Download/"+ URLUtil.guessFileName(f_url[0], null, null));
Log.i("File name",URLUtil.guessFileName(f_url[0], null, null));
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress("" + (int) ((total * 100) / lenghtOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
In there f_url is the firebase download url. Thank you.
The built in way of doing this is actually quite straightforward:
StorageReference reference = storage.getReferenceFromUrl("https://firebasestorage.googleapis.com/...");
// Assuming that the file is "name.extension" in Storage
String name = reference.getName().split(".")[0]
String extension = reference.getName().split(".")[1]
File localFile = File.createTempFile(name, extension);
reference.getFile(localFile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
// Local temp file has been created
}
});
But if you don't want to do it the easy way...
Let's take a brief look at how you're naming your file: URLUtil.guessFileName(f_url[0], null, null)
According to the URLUtil.guessFileName() docs: "Guesses canonical filename that a download would have, using the URL and contentDisposition. File extension, if not defined, is added based on the mimetype."
I'm assuming that your f_url[0] is a file with no extension, and since you provide no contentDisposition or mimetype as arguments to guessFileName, there's no way it can possibly know what file extension you want.
You can get the contentDisposition and contentType (same as mimetype) from Storage Metadata, and if you name your file in Storage with an extension, you should be good to go.

How to download all images one by one and show progress status

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.

InputStream Exception while downloading a file

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){
}

FileNotFoundExecption when trying to download PDF from URL with spaces

I'm trying to use the following code to download and then eventually view a PDF file. The URL of the file is like this:
http://www.example.com/directory/something.example.com This File.pdf
I've tried replacing the spaces with %20, I've tried "UrlEncoder.encode", no matter what I get either FileNotFoundException or MalformedURLException (when encoding the URL). Example exceptions:
java.io.FileNotFoundException:
http://www.example.com/directory/something.example.com This File.pdf
java.io.FileNotFoundException:
http://www.example.com/directory/something.example.com%20This%20File.pdf
java.net.MalformedURLException: Protocol not found:
http%3A%2F%2Fwww.example.com%directory%2Fsomething.example.com+This+File.pdf
If I copy those paths into any browser it downloads fine.
File file;
try
{
String urlString =
"http://www.example.com/directory/something.example.com This File.pdf"
URL url = new URL(urlString);
//URL url = new URL(URLEncoder.encode(urlString, "UTF-8"));
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
file = new File(getExternalFilesDir(null), "test.pdf");
FileOutputStream fileOutput = new FileOutputStream(file);
InputStream inputStream = urlConnection.getInputStream();
byte[] buffer = new byte[1024 * 1024];
int bufferLength;
while ((bufferLength = inputStream.read(buffer)) > 0)
{
fileOutput.write(buffer, 0, bufferLength);
}
fileOutput.flush();
fileOutput.close();
inputStream.close();
return file.getAbsolutePath();
}
catch (Exception e)
{
Log.e(getClass().getSimpleName(), e.getMessage(), e);
return "";
}
The exception java.io.FileNotFoundException will be returned if the server responds with a 404 error code. Sometimes the error code and the data returned do not match. You can check for this (and get whatever data was returned) using the following:
boolean isError = urlConnection.getResponseCode() >= 400;
InputStream inputStream = = isError ? urlConnection.getErrorStream() : urlConnection.getInputStream();
And if you're connecting to a non-standard port, you can fix it by adding these headers to your request:
urlConnection.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) ");
urlConnection.setRequestProperty("Accept","*/*");
Your UrlEncoder attempts have been wrong. Here's the javadoc:
http://docs.oracle.com/javase/6/docs/api/java/net/URLEncoder.html
java.io.FileNotFoundException:
http://www.example.com/directory/something.example.com This File.pdf
Spaces were not encoded so it doesn't match your file.
java.io.FileNotFoundException:
http://www.example.com/directory/something.example.com%20This%20File.pdf
%20 are valid url symbols, so this also doesn't match your file.
java.net.MalformedURLException: Protocol not found:
http%3A%2F%2Fwww.example.com%directory%2Fsomething.example.com+This+File.pdf
Slash after .com is not encoded properly. Results in an incorrectly encoded url.
With UrlEncoder, you should be encoding the file name and concatenating it with the URL, not encoding the entire url string and use UTF-8 encoding. Anything else (not UTF-8) is not guaranteed to work.
If manually encoding spaces don't then pass them through the UrlEncoder.

Categories

Resources