Downloading images from AWS gives me corrupt files - java

I'm trying to download images that are hosted on Amazon Web Services. My methods work fine on any other host, but downloading an image off this url for example http://s3-eu-west-1.amazonaws.com/static.melkweg.nl/uploads/images/scaled/event_header/18226 is giving me trouble. It does download, but the file is only 49kb big and cannot be opened.
I've tried different methods such as Apache's FileUtils copyURLToFile, BufferedInputStream, ImageIO, etc. Some throw errors, most just download a corrupt file.
Here are the methods I've tried:
public static void downloadApache(String imageurl, String target)
{
try
{
File file = new File(target);
URL url = new URL(imageurl);
FileUtils.copyURLToFile(url, file);
}
catch(Exception e)
{
System.err.println("[3]Something went wrong.");
}
}
public static void downloadImage(String imageurl, String name)
{
try
{
URL url = new URL(imageurl);
InputStream in = new BufferedInputStream(url.openStream());
OutputStream out = new BufferedOutputStream(new FileOutputStream(name));
for ( int i; (i = in.read()) != -1; ) {
out.write(i);
}
in.close();
out.close();
}
catch(Exception e)
{
e.printStackTrace();
System.err.println("[0]Something went wrong.");
}
}
public static void downloadImageIO(String imageurl, String target)
{
try
{
URL url = new URL(imageurl);
BufferedImage image = ImageIO.read(url);
ImageIO.write(image, "jpg", new File(target));
}
catch(Exception e)
{
e.printStackTrace();
System.err.println("[1]Something went wrong.");
}
}
public static void downloadImageCopy(String imageurl, String target)
{
try
{
try (InputStream in = new URL(imageurl).openStream()) {
Files.copy(in, Paths.get(target), StandardCopyOption.REPLACE_EXISTING);
}
}
catch(Exception e)
{
e.printStackTrace();
System.err.println("[2]Something went wrong.");
}
}
And here's the main method if that is of any interest
public static void main(String[] args)
{
String imageurl = "http://s3-eu-west-1.amazonaws.com/static.melkweg.nl/uploads/images/scaled/event_header/18226";
String name = "downloaded_image.jpg";
String target = "C:/Users/Robotic/Downloads/" + name;
Download.downloadImage(imageurl, name);
Download.downloadImageCopy(imageurl, target);
Download.downloadImageIO(imageurl, target);
Download.downloadApache(imageurl, target);
}
Thanks in advance.

The file that you are getting from S3 is gzip compressed, you need to decompress it before trying to read it.
$ wget http://s3-eu-west-1.amazonaws.com/static.melkweg.nl/uploads/images/scaled/event_header/18226
$ file 18226
18226: gzip compressed data, from Unix

As pointed out in the earlier answer, it is in gzip format.
You can use the following method and get the file unzipped
public static void downloadApache(String imageurl, String target) {
try {
File file = new File(target+".gzip");
URL url = new URL(imageurl);
FileUtils.copyURLToFile(url, file);
byte[] buffer = new byte[1024];
try {
java.util.zip.GZIPInputStream gzis = new java.util.zip.GZIPInputStream(new FileInputStream(file));
FileOutputStream out = new FileOutputStream(target);
int len;
while ((len = gzis.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
gzis.close();
out.close();
} catch (IOException ex) {
ex.printStackTrace();
}
} catch (Exception e) {
System.err.println("[3]Something went wrong.");
}
}

Related

How can I run executable in assets?

How can I add a executable into assets and run it in Android and show the output?
I've a executable that will work. I assume there will need to be some chmod in the code.
Thank you.
here is my answer
put copyAssets() to your mainactivity.
someone's code:
private void copyAssets() {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = assetManager.list("");
} catch (IOException e) {
Log.e("tag", "Failed to get asset file list.", e);
}
for(String filename : files) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
File outFile = new File(getFilesDir(), filename);
out = new FileOutputStream(outFile);
copyFile(in, out);
} catch(IOException e) {
Log.e("tag", "Failed to copy asset file: " + filename, e);
}
finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// NOOP
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
// NOOP
}
}
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
also here is code to run command
public String runcmd(String cmd){
try {
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer out = new StringBuffer();
while ((read = in.read(buffer)) > 0) {
out.append(buffer, 0, read);
}
in.close();
p.waitFor();
return out.substring(0);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
you may need to change it to
String prog= "programname";
String[] env= { "parameter 1","p2"};
File dir= new File(getFilesDir().getAbsolutePath());
Process p = Runtime.getRuntime().exec(prog,env,dir);
to ensure proper parameter handling
also add this to your main code
to check proper copying of files
String s;
File file4 = new File(getFilesDir().getAbsolutePath()+"/executable");
file4.setExecutable(true);
s+=file4.getName();
s+=file4.exists();
s+=file4.canExecute();
s+=file4.length();
//output s however you want it
should write: filename, true, true, correct filelength.
Place your executable in raw folder, then run it by using ProcessBuilder or Runtime.exec like they do here http://gimite.net/en/index.php?Run%20native%20executable%20in%20Android%20App

How to write html to a file in android

I know this has been asked a few times here, but I'm not sure which way I should go. This code downloads the html file okay, but I get an IOException when trying to write the html to a file. I've tried many suggestions on sof, but none seem to work for me and I'm at a loss as it seems it should be working.
class Downloader extends AsyncTask<URL, Void, Void> {
String site = getResources().getString(R.string.sched_hd_url);
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File(sdCard.getAbsolutePath() + "/directory/");
File file = new File(dir, "file.html");
#Override
protected Void doInBackground(URL... urls) {
try {
URL url = new URL(site);
URLConnection yc = url.openConnection();
BufferedInputStream in = new BufferedInputStream(new URL(site).openStream());
OutputStream out = new FileOutputStream(file);
int total = 0;
int count;
byte data1[] = new byte[1024];
while ((count = in.read(data1)) != -1) {
out.write(data1);
total += count;
}
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void result) {
progress.setVisibility(View.INVISIBLE);
finish();
}
}
I run this code and no file appears in the directory that I specified. The directory already exists, and I do have the permissions in my manifest. Any suggestions would be greatly appreciated.
So my problem was a couple of things. First, I want to thank those that commented. In my question, I did neglect to put in the out.close(); method. When that didn't work, I was looking at the string which held the URL I wanted to use. That had errors in it. This fixed the download problem, but I wanted to download from a place where the .html file was not in the URL (example: http://www.example.com/ instead of http://www.example.com/index.html). It worked for the latter but not the former. So instead of using URLConnection I used HttpURLConnection. Here is my working code:
class Downloader extends AsyncTask<URL, Void, Void> {
String site = getResources().getString(R.string.sched_hd_url);
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File(sdCard.getAbsolutePath() + "/directory/");
File file = new File(dir, "file.html");
#Override
protected Void doInBackground(URL... uri) {
FileOutputStream out = null;
if (file.exists()) {
try {
file.delete();
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
URL url = new URL(site);
HttpURLConnection yc = (HttpURLConnection) url.openConnection();
BufferedInputStream in = new BufferedInputStream(
new URL(site).openStream());
out = new FileOutputStream(file);
int total = 0;
int count;
byte data1[] = new byte[1024];
while ((count = in.read(data1)) != -1) {
out.write(data1);
total += count;
}
in.close();
out.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void result) {
progress.setVisibility(View.INVISIBLE);
finish();
}
}
Also another error in my question was in regards to no implementation checking to see if the file had already existed. Thanks again for the help.

Writing/Reading gif internal storage

I'm trying to load a gif from a url to be displayed in an Imageview, store it in the internal storage and then later read it again. But it refuses to either store the image or reading it, not sure which one because I get no exceptions. Loading the image to the imageview works. The first method below (loadImage())
public Bitmap loadImage(String url){
Bitmap bm = null;
URL request;
try {
if(url!=null){
request = new URL(url);
InputStream is = request.openStream();
bm = BitmapFactory.decodeStream(is);
is.close();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bm;
}
public String writeGifToInternalStorage (Bitmap outputImage) {
try {
String fileName = String.valueOf(Calendar.getInstance().getTimeInMillis());
ByteBuffer byteBuffer = ByteBuffer.allocate(outputImage.getByteCount());
outputImage.copyPixelsToBuffer(byteBuffer);
byteBuffer.flip();
byte[] data = new byte[byteBuffer.limit()];
byteBuffer.get(data);
FileOutputStream fos = ctx.openFileOutput(fileName, Context.MODE_PRIVATE);
fos.write(data);
fos.close();
return fileName;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public Bitmap readFileFromInternalStorage(String filename) {
if (filename == null) return null;
FileInputStream fis;
try {
fis = ctx.openFileInput(filename);
return BitmapFactory.decodeStream(fis);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
Any ideas of whats wrong?
Your method readFileFromInternalStorage read an encoded image from the file system. This image file should be what you receive from the server.
For that, you need to save the image when you receive it from the server, for example like so:
InputStream is = new BufferedInputStream(request.openStream());
String fileName = String.valueOf(Calendar.getInstance().getTimeInMillis());
FileOutputStream fos = ctx.openFileOutput(fileName, Context.MODE_PRIVATE);
byte[] buffer = new byte[1024];
int red = 0;
while ((red = is.read(buffer)) != -1) {
fos.write(buffer,0, red);
}
fos.close();
is.close();
Then, your image is saved to the disk, and you can open it using your readFileFromInternalStorage method.
Also, if you use HttpClient instead of URL, I wrote a one-liner for downloading a file: Android download binary file problems

Parse a Path from Java program

Have a file on specified path /foo/file-a.txt and that file contains a path of another file
file-a.txt contains: /bar/file-b.txt this path at line one. need to parse the path of file-b.txt and zip that file and move that zipped file to another path /too/ from my Java code.
I been till the below code then i m stuck.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Reader
{
public static void main(String[] args)
{
BufferedReader br = null;
try
{
String CurrentLine;
br = new BufferedReader(new FileReader("/foo/file-a.txt"));
while ((CurrentLine = br.readLine()) != null)
{
System.out.println(CurrentLine);
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if (br != null)br.close();
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
}
am getting path as text, help would be appreciated. Thanks in advance
For the actual zipping of the file, this page may be of help.
As a general note, this code will replace the current existing zip file.
public class TestZip02 {
public static void main(String[] args) {
try {
zip(new File("TextFiles.zip"), new File("sample.txt"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void zip(File zip, File file) throws IOException {
ZipOutputStream zos = null;
try {
String name = file.getName();
zos = new ZipOutputStream(new FileOutputStream(zip));
ZipEntry entry = new ZipEntry(name);
zos.putNextEntry(entry);
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
byte[] byteBuffer = new byte[1024];
int bytesRead = -1;
while ((bytesRead = fis.read(byteBuffer)) != -1) {
zos.write(byteBuffer, 0, bytesRead);
}
zos.flush();
} finally {
try {
fis.close();
} catch (Exception e) {
}
}
zos.closeEntry();
zos.flush();
} finally {
try {
zos.close();
} catch (Exception e) {
}
}
}
}
For moving the file, you can use File.renameTo, here's an example.
Hope this helps!

How to download a text file via FTP and read the contents to a string

This is re-worded from a previous question (which was probably a bit unclear).
I want to download a text file via FTP from a remote server, read the contents of the text file into a string and then discard the file. I don't need to actually save the file.
I am using the Apache Commons library so I have:
import org.apache.commons.net.ftp.FTPClient;
Can anyone help please, without simply redirecting me to a page with lots of possible answers on?
Not going to do the work for you, but once you have your connection established, you can call retrieveFile and pass it an OutputStream. You can google around and find the rest...
FTPClient ftp = new FTPClient();
...
ByteArrayOutputStream myVar = new ByteArrayOutputStream();
ftp.retrieveFile("remoteFileName.txt", myVar);
ByteArrayOutputStream
retrieveFile
Normally I'd leave a comment asking 'What have you tried?'. But now I'm feeling more generous :-)
Here you go:
private void ftpDownload() {
FTPClient ftp = null;
try {
ftp = new FTPClient();
ftp.connect(mServer);
try {
int reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
throw new Exception("Connect failed: " + ftp.getReplyString());
}
if (!ftp.login(mUser, mPassword)) {
throw new Exception("Login failed: " + ftp.getReplyString());
}
try {
ftp.enterLocalPassiveMode();
if (!ftp.setFileType(FTP.BINARY_FILE_TYPE)) {
Log.e(TAG, "Setting binary file type failed.");
}
transferFile(ftp);
} catch(Exception e) {
handleThrowable(e);
} finally {
if (!ftp.logout()) {
Log.e(TAG, "Logout failed.");
}
}
} catch(Exception e) {
handleThrowable(e);
} finally {
ftp.disconnect();
}
} catch(Exception e) {
handleThrowable(e);
}
}
private void transferFile(FTPClient ftp) throws Exception {
long fileSize = getFileSize(ftp, mFilePath);
InputStream is = retrieveFileStream(ftp, mFilePath);
downloadFile(is, buffer, fileSize);
is.close();
if (!ftp.completePendingCommand()) {
throw new Exception("Pending command failed: " + ftp.getReplyString());
}
}
private InputStream retrieveFileStream(FTPClient ftp, String filePath)
throws Exception {
InputStream is = ftp.retrieveFileStream(filePath);
int reply = ftp.getReplyCode();
if (is == null
|| (!FTPReply.isPositivePreliminary(reply)
&& !FTPReply.isPositiveCompletion(reply))) {
throw new Exception(ftp.getReplyString());
}
return is;
}
private byte[] downloadFile(InputStream is, long fileSize)
throws Exception {
byte[] buffer = new byte[fileSize];
if (is.read(buffer, 0, buffer.length)) == -1) {
return null;
}
return buffer; // <-- Here is your file's contents !!!
}
private long getFileSize(FTPClient ftp, String filePath) throws Exception {
long fileSize = 0;
FTPFile[] files = ftp.listFiles(filePath);
if (files.length == 1 && files[0].isFile()) {
fileSize = files[0].getSize();
}
Log.i(TAG, "File size = " + fileSize);
return fileSize;
}
You can just skip the download to local filesystem part and do:
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(server, port);
ftpClient.login(user, pass);
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
InputStream inputStream = ftpClient.retrieveFileStream("/folder/file.dat");
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "Cp1252"));
while(reader.ready()) {
System.out.println(reader.readLine()); // Or whatever
}
inputStream.close();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
if (ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}

Categories

Resources