Image URL to File Object - android

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.

Related

Android - Load image byte by byte in imageview

I have a large size of the image file which is nearly 16MB size. I want to load this image in my imageView and zoom it after that add markers. I tried this with subsampling-scale-image-view. I am following the below link https://github.com/davemorrissey/subsampling-scale-image-view .
The important point is I am loading image from url. The above library not supporting that. So I just downloaded the image and save to SD card after that load from that local file. Technically which is working.
Issue:
Now the issue is it is taking too much of time for the first time downloading. Also even second time it takes nearly a minute.
My Idea:
Due to this issue, I try to load image byte by byte. Once the image is downloading 100bytes then show that in imageView next download the next part of the image from url. Is it possible to doing like that?
Currently I am loading image like the following code:
URL url = new URL(url_);
URLConnection conection = url.openConnection();
conection.connect();
// getting file length
int lenghtOfFile = conection.getContentLength();
// input stream to read file - with 8k buffer
InputStream input = new BufferedInputStream(url.openStream(), 8192);
// Output stream to write file
OutputStream output = new FileOutputStream(root+"/"+ fileName);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
runOnUiThread(new Runnable() {
#Override
public void run() {
image.setImage(ImageSource.uri(root+"/"+ fileName));
}
});
Can somebody help me to solve this riddle?
Note: If there are any possibilities other than this library pls add your suggestions.
Never tried this but you can check if this work.
Get the data from url in form of byte Array.
data = getImageStream(url); //should call in async Task..
Now convert byte array into bitmap and set in imageView.
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
image.setImageBitmap(bitmap)
Not writing into file.This will help with some performance improvement.
public byte[] getImageStream(String url){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = null;
try {
is = url.openStream ();
byte[] byteChunk = new byte[4096]; // Or whatever size you want to read in at a time.
int n;
while ( (n = is.read(byteChunk)) > 0 ) {
baos.write(byteChunk, 0, n);
}
}
catch (IOException e) {
System.err.printf ("Failed while reading bytes from %s: %s", url.toExternalForm(), e.getMessage());
e.printStackTrace ();
// Perform any other exception handling that's appropriate.
}
finally {
if (is != null) { is.close(); }
}
return baos.toByteArray();
}

Get files from web service

I have a URL(http://xxx.xxx/api/getFiles) which is returning a JSON response. According to the developer of the API, this link also return files (images, pdf, word, excel, video, etc) that we're going to download to our Android device.
This link returns a file path (e.g. "/File Folder/") and file name (e.g. "Penguins.jpg") that will be used to link the file to the web server but I don't have an idea how to do it.
Are there ways to download it using this API?
JSON response:
{
   "status":"success",
   "count":1,
   "files":[
      {
         "file_code":"2",
         "file_name":"Penguins.jpg",
         "file_type":".jpg",
         "file_path”:”\/File Folder\/“
      }
   ]
}
To download file from url following peice of code can help you:
This code will create connection with url server and download it to specified path:
int downloadedSize = 0;
int totalSize = 0;
try {
URL url = new URL("download file url");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
//connect
urlConnection.connect();
//set the path where we want to save the file
File SDCardRoot = Environment.getExternalStorageDirectory();
//create a new file, to save the downloaded file
File file = new File(SDCardRoot, "DownloadFileNameWithExtension"); // like test.png
FileOutputStream fileOutput = new FileOutputStream(file);
//Stream used for reading the data from the internet
InputStream inputStream = urlConnection.getInputStream();
//this is the total size of the file which we are downloading
totalSize = urlConnection.getContentLength();
//create a buffer...
byte[] buffer = new byte[1024];
int bufferLength = 0;
while ((bufferLength = inputStream.read(buffer)) > 0) {
fileOutput.write(buffer, 0, bufferLength);
downloadedSize += bufferLength;
}
//close the output stream when complete //
fileOutput.close();
} catch (final MalformedURLException e) {
e.printStackTrace();
} catch (final IOException e) {
e.printStackTrace();
} catch (final Exception e) {
e.printStackTrace();
}
Don't forget to add Internet permission in your manifest:D

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

How to copy large files in Android?

I am trying to copy a large pdf-file (3.7 mb) from my raw-folder to the external cache directory.
I a using the following piece of code:
int i = 0;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
{
InputStream input = getResources().openRawResource(pdfs[i]);
File file = new File(Environment.getExternalStorageDirectory(), "/Android/data/eu.app/cache/" + pdfNames[i]);
if(!file.exists())
{
try
{
new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/eu.app/cache").mkdirs();
FileOutputStream fos = new FileOutputStream(file.toURI().getPath(), false);
OutputStream os = new BufferedOutputStream(fos);
byte[] buffer = new byte[1024];
int byteRead = 0;
while ((byteRead = input.read(buffer)) != -1) {
os.write(buffer, 0, byteRead);
}
fos.close();
}
catch(Exception ex)
{
Log.d("storage", ex.getMessage());
}
}
}
else
{
}
I don't get any errors, but the output-file is a few bytes smaller than the original and cannot be opened.
What do I need to do to fix this?
I think the main issue is that you close fos while you should close os. You also need to put the close operation in a finally block.
Update (now with a full keyboard ;)): You close the file stream (fos) before the buffered stream is flushed. What you should do is to close the buffered stream (os), and that will in turn flush its buffer and write those bytes that are missing, and then it will automatically close the underlying file stream. To fix it change fos.close() into os.close().
In addition, to make sure that you always close the stream you should place the close operation in a finally block. A typical pattern is the following:
BufferedInputStream in = null;
try {
in = new BufferedInputStream(anInputStream);
BufferedOutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream(aFile));
// Read and write what you should write
}
finally {
if (out != null) out.close();
}
} finally {
if (in != null) in.close();
}
You can easily add an input stream, but be careful to make sure all streams are closed. This can be handled by nesting finally blocks or nesting try-catch blocks inside the finally block.
Either you throw an IOException from this method and handle it outside (often preferred), or you wrap the above code in a new try-catch statement and handle it there. However, handling it within the method mixes UI with logic and the code is often clearer separating UI and logic.
A final note: 1024 is rather small. Play with different values. On the other hand the buffered stream will handle the buffering for you.
I've been using this function for reading from one stream to another for a few years and have never had any problems with the resulting file. Just open the source and target files as you are and pass their respective streams into this function:
public static void streamToStream(InputStream is, OutputStream os) {
int count = 0;
try {
while(count != -1) {
byte[] bytes = new byte[2048];
count = is.read(bytes);
if(count == -1) {
continue;
}
os.write(bytes, 0, count);
bytes = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}

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

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

Categories

Resources