Load image in a String and save after change image - java

I'm trying load an image in a string and after do something with this String, save the image.
The problem appear when i try to asignate the value of the FileInputStream to the String targetFileStr. If i don't to this, and I save the image, everything it's ok, but when i save it on the String, the image change, no matter if I try save the image from the String or from the FileInputStream.
FileInputStream fis = null;
File file = new File("image.png");
fis = new FileInputStream(file);
String targetFileStr = IOUtils.toString(fis, "UTF-8");
*InputStream inputStream = IOUtils.toInputStream(targetFileStr, "UTF-8");
*InputStream inputStream = fis;
// no matter which one i use, both ways fail
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(new File("image2.png"));
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
} catch (Exception e) {
e.printStackTrace();
}

You may want to consider converting the image into a String via Base64 encoding/decoding. This is an example of encoding.
After encoding, you can modify the String (actually you create new strings, you cannot modify the existing one), but be sure to produce valide base64-encoded outputs, otherwise you won't be able to decode.

Related

send images through java android sockets

I want to send images through sockets but I have not been able to do it in android, could someone help me?
System.out.println("iniciooooo");
//converting image to bytes with base64
Bitmap b = BitmapFactory.decodeFile("/sdcard/ajeffer.jpg");
ByteArrayOutputStream byte2= new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.JPEG,70,byte2);
byte[] enbytes = byte2.toByteArray();
String bb = Base64.encodeToString(enbytes,Base64.DEFAULT);
System.out.println(Base64.encodeToString(enbytes,Base64.DEFAULT));
data.writeUTF(bb);
FileOutputStream file;
//receiving the image in bytes to convert it into an image
DataInputStream dain = new DataInputStream(s.getInputStream());
msg = dain.readUTF();
File ff = new File("/sdcard/a2jeffer.jpg");
byte[] deco = Base64.decode(dain.readUTF(),Base64.DEFAULT);
Bitmap bit = BitmapFactory.decodeByteArray(deco,0,deco.length);
file = new FileOutputStream(ff);
bit.compress(Bitmap.CompressFormat.JPEG,70,file);
//the image is not created
I realized that my code did not work because I had to put this android: requestLegacyExternalStorage =" true " in the manifest, also I see that you are right about writeUTF () since in order to send images I must drastically lower the quality but it works If you have an idea on how to improve this, let me know, thank you very much.
You were right, this works great for sending and receiving any file.
Send file
OutputStream outputStream = socket.getOutputStream();
InputStream inputStream = new FileInputStream(file);
byte[] datita = new byte[16*1024];
int count;
while((count = inputStream.read(datita))>0){
outputStream.write(datita,0,count);
}
outputStream.close();
inputStream.close();
Receive file
OutputStream outputStream = new FileOutputStream(file);
InputStream inputStream = s.getInputStream();
byte[] datita = new byte[16*1024];
int count;
while((count = inputStream.read(datita))>0){
outputStream.write(datita,0,count);
}
outputStream.close();
inputStream.close();

downloaded file supposed to be .png

i dont know whats wrong with my code, i try to download png from server with sambautil
if (!path.equals("")) {
SambaUtil su = new SambaUtil();
byte[] data = su.openfile(path);
log.info(path);
ByteArrayInputStream inStream = new ByteArrayInputStream(su.openfile(path));
PrintWriter outStream1 = resp.getWriter();
int bytes;
while ((bytes = inStream.read()) != -1) {
outStream1.write(bytes);
}
inStream.close();
outStream1.close();
}
the connection is right, but output data seems wrong
the output
Any idea?
That is because you are taking the bytes that make up the .PNG file and printing it out instead of saving it as a file which is what I think you want to do.
Instead of
PrintWriter outStream1 = resp.getWriter();
Replace with this
OutputStream outStream1 = new FileOutputStream("somefile.png");
Then open the 'somefile.png' and you should be able to see the image that you downloaded via Samba

Extream usage of RAM memory by ByteArrayOutputStream

So my problem sounds like this. I need to make a base64 encoded string of a file and for this, I use this method:
public String getStringFile(File f) {
InputStream inputStream = null;
String encodedFile= "", lastVal;
try {
inputStream = new FileInputStream(f.getAbsolutePath());
byte[] buffer = new byte[10240];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);
while ((bytesRead = inputStream.read(buffer)) != -1) {
output64.write(buffer, 0, bytesRead);
}
output64.close();
encodedFile = output.toString();
} catch (Exception e) {
e.printStackTrace();
}
lastVal = encodedFile;
return lastVal;
}
and the thing is when I try to encode file something around 20 Mb (exact file size is 19,35 Mb) I get an OutOfMemoryException.
Before:
After:
What am I doing wrong and how can I fix this issue? Thanks in advance.
What am I doing wrong
You are attempting to encode a ~20MB file using base64 into a string. You will not have adequate heap space on many Android devices to have a single memory allocation that large.
how can I fix this issue?
If "this issue" is "create a ~26MB string of base64-encoded data", there is no reliable way to do this. You would have to find some other solution to whatever problem you are trying to solve by creating such a string.
ByteArrayOutputStream output = new ByteArrayOutputStream();
Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);
If you upload the base64 yourself with HttpUrlConnection you can do way with the ByteArrayOutputStream and replace above lines -while directly uploading- with
OutputStream output = con.getOutputStream();
Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);
Untested.
You could also directly base64 encode to a FileOutputStream of course.
OutputStream output = new FileOutputStream(......);
Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);
and then upload that file with POJO.

How can I put a downloadable file into the HttpServletResponse?

I have the following problem: I have an HttpServlet that create a file and return it to the user that have to receive it as a download
byte[] byteArray = allegato.getFile();
InputStream is = new ByteArrayInputStream(byteArray);
Base64InputStream base64InputStream = new Base64InputStream(is);
int chunk = 1024;
byte[] buffer = new byte[chunk];
int bytesRead = -1;
OutputStream out = new ByteArrayOutputStream();
while ((bytesRead = base64InputStream.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
As you can see I have a byteArray object that is an array of bytes (byte[] byteArray) and I convert it into a file in this way:
First I convert it into an InputStream object.
Then I convert the InputStream object into a Base64InputStream.
Finally I write this Base64InputStream on a ByteArrayOutputStream object (the OutputStream out object).
I think that up to here it should be ok (is it ok or am I missing something in the file creation?)
Now my servlet have to return this file as a dowload (so the user have to receive the download into the browser).
So what have I to do to obtain this behavior? I think that I have to put this OutputStream object into the Servlet response, something like:
ServletOutputStream stream = res.getOutputStream();
But I have no idea about how exactly do it? Have I also to set a specific MIME type for the file?
It's pretty easy to do.
byte[] byteArray = //your byte array
response.setContentType("YOUR CONTENT TYPE HERE");
response.setHeader("Content-Disposition", "filename=\"THE FILE NAME\"");
response.setContentLength(byteArray.length);
OutputStream os = response.getOutputStream();
try {
os.write(byteArray , 0, byteArray.length);
} catch (Exception excp) {
//handle error
} finally {
os.close();
}
EDIT:
I've noticed that you are first decoding your data from base64, the you should do the following:
OutputStream os = response.getOutputStream();
byte[] buffer = new byte[chunk];
int bytesRead = -1;
while ((bytesRead = base64InputStream.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
You do not need the intermediate ByteArrayOutputStream
With org.apache.commons.compress.utils.IOUtils you can just "copy" from one file or stream (e.g. your base64InputStream) to the output stream:
response.setContentType([your file mime type]);
IOUtils.copy(base64InputStream, response.getOutputStream());
response.setStatus(HttpServletResponse.SC_OK);
You'll find that class here https://mvnrepository.com/artifact/org.apache.commons/commons-compress
A similar class (also named IOUtils) is also in Apache Commons IO (https://mvnrepository.com/artifact/commons-io/commons-io).

Image size increased if image convert to byte array

I need to upload image (jpeg, png, gif) and audio (mp3, wav, aa3) to web server. So I need to convert image into byte array. How do I do that?
Now I am try following format. But it increases the size. How do other applications do this without increasing size quality? They upload the original size and image quality.
Bitmap uploadedImage = ((BitmapDrawable) temp.getDrawable()).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
uploadedImage.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] bytes = stream.toByteArray();
Original images increase in size when converted to a bitmap because all the image formats you mentioned use some form of compression (some lossless, some not). When you use a bitmap, there's no compression used.
You could read the raw data of the drawable into a byte array and send that to the server. You can check that answer Reading a resource sound file into a Byte array to see an example of how this could be done.
Presumably you have the Image in some sort of form already? Don't try to decompress or process it, just send it to the server as a stream of bytes. For example if it is already a file on your computer:
public String postFile(URL url, InputStream in) throws IOException {
try {
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
connection.setRequestMethod("POST");
connection.setChunkedStreamingMode(CHUNK_SIZE);
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type","application/octet-stream");
try (OutputStream out = connection.getOutputStream()) {
byte[] buffer = new byte[CHUNK_SIZE];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
}
if (connection.getResponseCode() != 201) {
try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getErrorStream()))) {
// TODO: Handle error
}
} else {
try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
// TODO: Handle success
}
}
} finally {
connection.disconnect();
}
}
To send a file just pass in the FileInputStream, to send bytes you can simplify the function above so it doesn't need to read from the stream and can just send the byte buffer on the output stream.
To get an InputStream for a local file you just need:
File file = ....
try (InputStream is = new FileInputStream(file)) {
postFile(url, is);
} catch (FileNotFoundException ex) {
// TODO: Handle error
}
No need to compress. Just send as stream. once got the image uri do the following..
InputStream iStream = context.getContentResolver().openInputStream(uri);
and use the iStream into write the httpsurlconnection.

Categories