I have a sample code to download some data (pdf,gif and mp3) from a web and its a swing application.It works perfectly in Windows 7 but not working in Windows xp.
My code is
public static Float downloadFile(String targetUrl,File filePath)
{
try
{
Integer count=0;
URL url = new URL(targetUrl);
HttpURLConnection connection=(HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setConnectTimeout(10000);
connection.connect();
int lenghtOfFile = connection.getContentLength();
Thread.sleep(100);
InputStream input = new BufferedInputStream(url.openStream());
Thread.sleep(100);
OutputStream output = new FileOutputStream(filePath);
byte data[] = new byte[input.available()];
long total = 0;
while ((count = input.read(data)) != -1)
{
total += count;
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
}
catch (Exception e)
{
e.printStackTrace();
}
return 2.5f;
}
}
It enters into the infinite while loop by setting the code to 0
Q: What is "input.available()" when you initialize your buffer? If it happens to be "0" at that moment, you'd be sad.
One solution is to use a fixed-length buffer (e.g. 8192).
Related
When I am downloading a file from the server if suppose I killed or destroy the application means it will download only half of data how to resume download when application open or how to delete incomplete data in the file.
Any ideas?
private void downloadBookDetails(String pMainFolder, String pFileName, String pDownloadURL) {
Log.i(TAG, "Coming to this downloadBookDetails ");
try {
URL url = new URL(pDownloadURL);
URLConnection ucon = url.openConnection();
ucon.setReadTimeout(5000);
ucon.setConnectTimeout(10000);
InputStream is = ucon.getInputStream();
BufferedInputStream inStream = new BufferedInputStream(is, 1024 * 5);
File directory = new File(pMainFolder, pFileName);
FileOutputStream outStream = new FileOutputStream(directory);
byte[] buff = new byte[5 * 1024];
int len;
while ((len = inStream.read(buff)) != -1) {
outStream.write(buff, 0, len);
}
outStream.flush();
outStream.close();
inStream.close();
} catch (Exception e) {
//Add Network Error.
Log.e(TAG, "Download Error Exception " + e.getMessage());
e.printStackTrace();
}
}
You should use DownLoad Manager for downloads in your app. This will automatically handles all the things for you. Which is a system service that can handle long-running HTTP downloads.
UPDATE
If you want to download the file by your own then you can use it like below:
#SuppressLint("Wakelock")
#Override
protected String doInBackground(String... sUrl) {
// take CPU lock to prevent CPU from going off if the user
// presses the power button during download
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
getClass().getName());
wl.acquire();
try {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
File SDCardRoot = Environment.getExternalStorageDirectory();
File file = new File(SDCardRoot,"/"+fileName);
int downloaded=0;
if(file.exists()){
downloaded=(int) file.length();
connection.setRequestProperty("Range", "bytes=" + (int) file.length() + "-");
}
else{
file.createNewFile();
}
connection.setDoInput(true);
connection.setDoOutput(true);
connection.connect();
// expect HTTP 200 OK, so we don't mistakenly save error report
// instead of the file
// this will be useful to display download percentage
// might be -1: server did not report the length
int fileLength = connection.getContentLength()+(int)file.length();
// download the file
input = connection.getInputStream();
if(downloaded>0){
output = new FileOutputStream(file,true);
}
else{
output = new FileOutputStream(file);
}
byte data[] = new byte[1024];
long total = downloaded;
int count;
mProgressDialog.setMax(fileLength/1024);
while ((count = input.read(data)) != -1) {
// allow canceling with back button
if (isCancelled())
return null;
total += count;
// publishing the progress....
if (fileLength > 0) // only if total length is known
publishProgress((int)total/1024);
output.write(data, 0, count);
}
output.flush();
if (output != null)
output.close();
if (input != null)
input.close();
if (connection != null)
connection.disconnect();
wl.release();
return null;
} catch (Exception e) {
return e.toString();
}
}
catch (Exception e) {
return e.toString();
}
}
My app saves some images in internal storage when the app is loading.
The problem is that the app is using the most common code for this situation, which is compressing the image before saving it, but this compressing process takes too long to be processed. For example, if there are 5 pictures to be loaded, the app take about 30 seconds to load and open the home screen. 30 seconds is too long to open an app.
My code to save the image is the following:
public static final boolean savePngLocalStorage(String fileName, Bitmap bitmap, Context context) throws IOException {
BufferedOutputStream bos = null;
Bitmap tmp = null;
try {
bos = new BufferedOutputStream(context.openFileOutput(fileName, Context.MODE_PRIVATE)); //他アプリアクセス不可
tmp = bitmap.copy(Config.ARGB_8888, true);
return tmp.compress(Bitmap.CompressFormat.PNG, 100, bos);
} finally {
if (tmp != null) {
tmp.recycle();
tmp = null;
}
//
try {
bos.close();
} catch (Exception e) {
//IOException, NullPointerException
}
}
}
Using debug, I realized that tmp.compress command is the one that take some time to be processed.
I tried to use the following code without compressing the image. It got a bit faster.
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
ContextWrapper c = new ContextWrapper(MainActivity.this);
File path = c.getFilesDir();
String fileName = imageIdArray[i] + ".png";
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(path + "/" + fileName); // "data/data/[package_name]/files/sample.png"
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
Are there other ways to save the image faster?
FileOutputStream out = null;
String path = setOutputFilePath();
try {
out = new FileOutputStream(path);
croppedBitmap2.compress(Bitmap.CompressFormat.JPEG, 100, out); // bmp is your Bitmap instance
// PNG is a lossless format, the compression factor (100) is ignored
LOGGER.debug("Saving image on the absolute path folder!");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
I am trying to download a file (mp3) from my server.
I want to show the downloading progress, but I am facing a problem that whole time the file size is -1.
The screenshot:
My code:
try {
URL url = new URL(urls[0]);
// URLConnection connection = url.openConnection();
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.connect();
int fileSize = connection.getContentLength();
if (fileSize == -1)
fileSize = connection.getHeaderFieldInt("Length", -1);
InputStream is = new BufferedInputStream(url.openStream());
OutputStream os = new FileOutputStream(myFile);
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = is.read(data)) != -1) {
total += count;
Log.d("fileSize", "Lenght of file: " + fileSize);
Log.d("total", "Lenght of file: " + total);
// publishProgress((int) (total * 100 / fileSize));
publishProgress("" + (int) ((total * 100) / fileSize));
os.write(data, 0, count);
}
os.flush();
os.close();
is.close();
} catch (Exception e) {
e.printStackTrace();
}
I get the garbage value for the fileSize which return -1 (int fileSize = connection.getContentLength();)
Inspect the headers the server is sending. Very probably the server is sending Transfer-Encoding: Chunked and no Content-Length header at all. This is a common practice in HTTP/1.1. If the server isn't sending the length, the client obviously can't know it. If this is the case, and you have no control over the server code, the best thing to do is probably display a spinner type of indicator only.
Im not sure why this is happening from time to time but file sizes differ when I upload to a remote ftp server.
Here is how I do this:
URLConnection uc;
try {
uc = Init.net.openConnection();
OutputStream os = uc.getOutputStream();
FileInputStream fis = new FileInputStream("List.jkm");
byte[] buffer = new byte[1024];
int count = 0;
while((count = fis.read(buffer)) > 0) {
os.write(buffer, 0, count);
}
fis.close();
os.flush();
} catch (IOException e1) {
e1.printStackTrace();
}
Appreciate some hints
I am using this code to download zip file from server
private static InputStream OpenHttpConnection(String urlString)
throws IOException
{
InputStream in = null;
int response = -1;
URL url = new URL(urlString);
URLConnection conn = url.openConnection();
if (!(conn instanceof HttpURLConnection))
throw new IOException("Not an HTTP connection");
try{
System.out.println("OpenHttpConnection called");
HttpURLConnection httpConn = (HttpURLConnection) conn;
httpConn.setAllowUserInteraction(false);
httpConn.setInstanceFollowRedirects(true);
httpConn.setRequestMethod("GET");
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestProperty("content-type", "binary/data");
httpConn.connect();
response = httpConn.getResponseCode();
System.out.println("response is"+response);
System.out.println(HttpURLConnection.HTTP_OK);
if (response == HttpURLConnection.HTTP_OK) {
in = httpConn.getInputStream();
System.out.println("Connection Ok");
return in;
}
}
catch (Exception ex)
{
throw new IOException("Error connecting");
}
return in;
}
and
private static void saveToInternalSorage(InputStream in,String filename,Context ctx){
//fos =openFileOutput(filename, Context.MODE_WORLD_READABLE);
try {
// System.out.println("mypath = "+mypath);
//fos = new FileOutputStream(mypath);
FileOutputStream fos = (ctx).openFileOutput(filename, Context.MODE_WORLD_READABLE);
byte[] buffer=new byte[1024];
int len1 ;
while ( (len1 = in.read(buffer) )!=-1 ) {
fos.write(buffer);
}
// Use the compress method on the BitMap object to write image to the OutputStream
} catch (Exception e) {
e.printStackTrace();
}
}
The zip file which is downloaded is corrupted , the actual size of the file is 3.5kb but the downloaded file is of 5kb .What is the problem with the code please help?
This
while ( (len1 = in.read(buffer) )!=-1 ) {
fos.write(buffer);
}
You are writing the entire buffer in each iteration (1024 bytes). You should only write len1 bytes (number of bytes read).
On a side-note, you may want to look at using some higher level abstraction libraries for stuff like HTTP and stream manipulation. Apache Commons HttpComponents and Commons IO for instance.
httpConn.setDoOutput(false);
httpConn.setRequestProperty("Content-Type", "application/octet-stream");
httpConn.setRequestProperty("Content-Length", String.valueOf(file.length());
while (... > 0) {
fos.write(buffer, 0, len1);
fos.close();
Write only the bytes which are filled in the buffer i.e only len1 bytes. It will solve your problem as if the buffer is not filled completely, we will write only those bytes which are read.
while ( (len1 = in.read(buffer) )!=-1 ) {
fos.write(subArray(buffer,len1));
}
//Method to create su-array
public byte[] subArray(byte[] arr, int length) {
byte temp[] = new byte[length];
for (int i = 0; i < length; i++) {
temp[i] = arr[i];
}
return temp;
}