Convert encoded base64 image to File object in Android - java

I am trying to use the AndroidImageSlider library and populate it with images that I have downloaded as a base64 string.
The library only accepts URLs, R.drawable values, and the File object as parameters.
I am trying to convert the image string to a File object in order to be passed to the library function. I have been able to decode from base_64 and convert to a byte[] so far.
String imageData;
byte[] imgBytesData = android.util.Base64.decode(imageData, android.util.Base64.DEFAULT);

You'll need to save the File object to disk for that to work. This method will save the imageData string to disk and return the associated File object.
public static File saveImage(final Context context, final String imageData) {
final byte[] imgBytesData = android.util.Base64.decode(imageData,
android.util.Base64.DEFAULT);
final File file = File.createTempFile("image", null, context.getCacheDir());
final FileOutputStream fileOutputStream;
try {
fileOutputStream = new FileOutputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
fileOutputStream);
try {
bufferedOutputStream.write(imgBytesData);
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
try {
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
It creates a temporary file in your applications 'cache' directory. However, you are still responsible for deleting the file once you no longer need it.

Related

Check the Succesfull Copy of a File

I am trying to make a file manager app in Android.
I want to provide the user with an option to move their files. So first I am copying the Files then I am deleting the file if there is no error.
This is the code I am using to copy the files
public static boolean copy(File copy, String directory, Context con) {
static FileInputStream inStream = null;
static OutputStream outStream = null;
DocumentFile dir = getDocumentFileIfAllowedToWrite(new File(directory), con);
String mime = "";
DocumentFile copy1 = dir.createFile(mime, copy.getName());
try {
inStream = new FileInputStream(copy);
outStream = con.getContentResolver().openOutputStream(copy1.getUri());
byte[] buffer = new byte[16384];
int bytesRead;
while ((bytesRead = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inStream.close();
outStream.close();
return true;
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
But in one of my devices the files are simply getting deleted without copying.
So my thought is that I will check the length of the file by SourceFile.length() and the length of the DestinationFile.length() if both are same or not. If both are same then I will delete the SourceFile.
Is the most effective way to check it without checking the MD5 of an File? Also what are the chances that the file transfer is incomplete/corrupted and still the length is same?

Uncompressing base64 gzip on S3 and saving to local file system

I am a Java bonehead/newbie so please be gentle. I have two functions which I realize are somewhat incompatible:
saveS3toFilesystem - takes a InputStream from AWS S3 and saves it to the local filesystem as a file
decompress - takes a string and decodes the base64 encoding and the decompresses the gzip compression.
I really want these two to work in concert to achieve the result of the file saved to the filesystem being the uncompressed file but I realize that my "decompress" function should probably be changed to receive a stream rather than a string but sadly I'm just a "cutter and paster" in the world of Java these days.
Here are my two functions as they are now:
private void saveS3toFilesystem(String filename, String bucketName, String localFilename) {
S3Object obj = s3.getObject(bucketName, filename);
InputStream in = obj.getObjectContent();
try {
Files.createDirectories(Paths.get(localFilename.replace(this.FILE_EXTENSION, "")));
Files.copy(in, Paths.get(localFilename));
this.logger.log("Input file has been placed in local filesystem for ITMS to pick up: " + localFilename + "\n");
} catch (IOException err) {
this.logger.log("There was a problem saving the file to " + localFilename);
err.printStackTrace();
} finally {
try {
in.close();
} catch (IOException err) {
err.printStackTrace();
}
}
return;
}
and then ...
private String decompress(String compressedZip) {
byte[] decodedBytes = Base64.getDecoder().decode(compressedZip);
String result = null;
GZIPInputStream zip = null;
try {
zip = new GZIPInputStream(new ByteArrayInputStream(decodedBytes));
result = IOUtils.toString(zip);
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(zip);
}
return result;
}
Can anyone please help me to achieve the dream? Happy to do it with streams, strings, or any method that will work. Sadly I can't afford atm to up my Java skills enough to grok the solution myself.
Many thanks in advance.
Based on the following APIs :
Base64.Decoder and GZIPInputStream (look at the wrap method on the former and the constructors on the latter), the decompress method can be overloaded as follows:
private String decompress(InputStream compressedStream) {
InputStream decodingStream = Base64.getDecoder().wrap(compressedStream);
String result = null;
GZIPInputStream zip = null;
try {
zip = new GZIPInputStream(decodingStream);
result = IOUtils.toString(zip);
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(zip);
}
return result;
}
And finally, the changes to saveS3toFilesystem are as follows :
private void saveS3toFilesystem(String filename, String bucketName, String localFilename) {
S3Object obj = s3.getObject(bucketName, filename);
InputStream in = obj.getObjectContent();
// decoding the inputstream via decode into a string, which is then
// used in order to create an inputstream of decoded data
InputStream decodedStream =
new ByteArrayInputStream(decompress(in).getBytes(StandardCharsets.UTF_8));
try {
Files.createDirectories(Paths.get(localFilename.replace(this.FILE_EXTENSION, "")));
Files.copy(decodedStream, Paths.get(localFilename));
this.logger.log("Input file has been placed in local filesystem for ITMS to pick up: " + localFilename + "\n");
} catch (IOException err) {
this.logger.log("There was a problem saving the file to " + localFilename);
err.printStackTrace();
} finally {
try {
in.close();
} catch (IOException err) {
err.printStackTrace();
}
}
return;
}

Read and write bitmap to android fails

I am trying to write and read a bitmap following the suggestions on other topics about this, the thing is i never get the bitmap when i try to read on the path where i saved the image:
So i have this to write the bitmap:
private String saveToInternalStorage(Bitmap bitmapImage){
ContextWrapper cw = new ContextWrapper(getApplicationContext());
// path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
// Create imageDir
File mypath=new File(directory,"captured");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return directory.getAbsolutePath();
}
}
i pass the returned path to another activity and then i pass it as parameter to get the bitmap like this:
private void loadImageFromStorage(String path)
{
try {
File f=new File(path, "captured.jpg");
Log.d("filehe",f.toString());
b = BitmapFactory.decodeStream(new FileInputStream(f));
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
}
i feel i am doing something wrong here, but can't figure out what, the b variavel has no value :/.
Any help?
Thanks
So i have this to write the bitmap:
The file that you save is named captured.
i pass the returned path to another activity and then i pass it as parameter to get the bitmap like this
Here, you are trying to load captured.jpg, which is not captured.
You could avoid this sort of problem by having the first method return the File that the second method then uses.
Also:
Use an image-loading library (e.g., Picasso, Glide) that has an in-memory cache, so you do not waste the user's time re-loading the same bitmap from disk
Get rid of ContextWrapper from the first method, as you do not need it

How to save an image in Android without compressing?

I'm making an Android application that captures images and stores them in the internal memory, but to save the images are compressed and I want to be saved in its original size without any compression.
This is the code I am using to store images, as I do so not me compress ??
ContextWrapper cw = new ContextWrapper(context);
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
File mypath = new File(directory, "TheChat" + (System.currentTimeMillis()/1000) + "Avatar.jpg");
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(mypath);
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
}
catch (Exception e) {
e.printStackTrace();
}
finally {
try {
if (fileOutputStream != null) {
fileOutputStream.flush();
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Save it as a BLOB (bytearray), then reconvert it to a bitmap upon loading it. If it's for internal use only it should work fine. If you're not compressing it at all you might as well save it in a straight-forward format.

OutofMemory error while writing a large file Android

I'm trying to encrypt a large file which is 500MB but my code throws an out of memory error, for small files below 50MB the code works fine. Im using a third party library called JNCryptor for encryption, please have a look at my code and correct me if any mistake. Thanks in advance.
public void encrypt() {
String file = Environment.getExternalStorageDirectory() + "/sai/ravi_enc.exe";
byte[] filedata = null;
try {
filedata = IOUtils.toByteArray(new FileInputStream(file));
} catch (IOException e) {
e.printStackTrace();
}
JNCryptor cryptor = new AES256JNCryptor();
String password = "123456789";
try {
byte[] ciphertext = cryptor.decryptData(filedata, password.toCharArray());
String Outfile = Environment.getExternalStorageDirectory() + "/sai/ravi_dec.exe";
writeFile(ciphertext, Outfile);
System.out.println("Done");
} catch (CryptorException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void writeFile(byte[] data, String fileName) throws IOException {
FileOutputStream out = new FileOutputStream(fileName);
out.write(data);
out.close();
}
This is up to JNCryptor to well manage memory, especially if it uses temp buffer. It is better to work on streams instead of buffers. Just for testing, if you write directly the fileData to your outFile, do you get OutOfMemoryError?
writeFile(filedata, Outfile);

Categories