Image byte stream is different when file is read in different ways - java

Under my Spring 4.3/Maven 3.3 project I have an image file, a PNG file, at:
src/main/resources/images/account.png
I have a util java application file that reads in an image, and it writes it to the database field. The code is as follows:
private static String _accountFilename = "src/main/resources/images/account.png";
private byte[] getByteArrayFromFile(String filename)
{
FileInputStream fileInputStream = null;
File file = new File(filename);
byte[] bFile = new byte[(int) file.length()];
try
{
// convert file into array of bytes
fileInputStream = new FileInputStream(file);
fileInputStream.read(bFile);
fileInputStream.close();
for (int i = 0; i < bFile.length; i++)
{
System.out.print((char) bFile[i]);
}
System.out.println("Done");
}
catch (Exception e)
{
e.printStackTrace();
}
return bFile;
}
public String getImageData(byte[] imageByteArray)
{
Base64.Encoder encoder = Base64.getEncoder();
String base64 = encoder.encodeToString(imageByteArray);
base64 = "data:image/png;base64," + base64;
return base64;
}
The String that comes back from "getImageData" works great. I can put that String in the MySQL database, in a table, and the field is defined as TEXT.
I can pull that base64 encoded data back, and display the image.
Now, If I am calling this code from a Spring Service instead of an application, then the image "src/main/resources/images/account.png" is not found.
After researching on the Net for some time, there are many, many examples of getting a file from "resources" and many of these did not work for me. Since I am in Spring, I tried a few things and finally this worked:
#Value(value = "classpath:images/account.png")
private Resource defaultAccountImage;
private byte[] getByteArrayFromFile(Resource image)
{
InputStream inputStream = null;
byte[] bFile = null;
try
{
bFile = new byte[(int) image.contentLength()];
// convert file into array of bytes
inputStream = image.getInputStream();
inputStream.read(bFile);
inputStream.close();
for (int i = 0; i < bFile.length; i++)
{
System.out.print((char) bFile[i]);
}
System.out.println("Done");
}
catch (Exception e)
{
e.printStackTrace();
}
return bFile;
}
private String getImageData(byte[] imageByteArray)
{
Base64.Encoder encoder = Base64.getEncoder();
String base64 = encoder.encodeToString(imageByteArray);
base64 = "data:image/png;base64," + base64;
return base64;
}
public String getDefaultAccountImage()
{
byte[] accountImage = getByteArrayFromFile(defaultAccountImage);
String fileString = getImageData(accountImage);
return fileString;
}
When I look at the String/Image data between the first way with the standalone java app, and the second way with the #Value and inputstream, there is a definite different in the string data.
part of the string data is similar, but then it drastically changes, and they don't match. As a result the text data for the image from the second method doesn't display as an image.
So, I was hoping I could get this image text data, and it would be the same, but it is not. If I can use my web-service, which calls the business service which calls this ImageUtil code where I use the #Value to get the image resource and it saves the text string correctly, that would be great.
If you have any advice, I would very much appreciate it. Thanks!
UPDATE 1:
This is a multi-maven project:
parent-project
entity
dao
service
ws
When I run my test code within the Service layer, the suggested solution works great! The images are found and the byte string gets loaded as it should be. And then I compiled the code into a jar.
The entity.jar gets created first.
The dao.jar gets created and pulls in the entity.jar.
The service.jar gets created and pulls in the dao.jar. This layer also has the /resources/images/account.png file. But this image is now in the jar.
The ws.WAR file pulls in the service.jar file ...
so the code in the answer does not find the image in the resources.
When I run the tests from the ws layer, I get a FileNotFoundException.
So ... now I am researching on how to get an image from jar ...
Does this change how I should be getting my image byte array?

You can get the file from the Resource, and proceed like the first example which works. Seems redundant, but if you can get the file, then you can test a number of things:
Write the file to disk and check the content
Write the file to disk and compare the sizes, etc.
import java.io.File;
import java.io.FileInputStream;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
#Value(value = "classpath:images/account.png")
private Resource defaultAccountImage;
private byte[] getByteArrayFromFile(Resource image) {
FileInputStream fileInputStream = null;
byte[] bFile = null;
try {
File file = image.getFile();
bFile = new byte[(int) file.length()];
// convert file into array of bytes
fileInputStream = new FileInputStream(file);
fileInputStream.read(bFile);
fileInputStream.close();
for (int i = 0; i < bFile.length; i++) {
System.out.print((char) bFile[i]);
}
System.out.println("Done");
} catch (Exception e) {
e.printStackTrace();
}
return bFile;
}

Related

How to temporarily create a text file without any file location and send as a response in spring boot at run time?

Need to create a txt file by the available data and then need to send the file as rest response.
the app is deployed in container. i dont want to store it in any location on container or any location in spring boot resources. is there any way where we can create file at runtime buffer without giving any file location and then send it in rest response?
App is production app so i need a solution which is secure
A file is a file. You're using the wrong words - in java, the concept of a stream of data, at least for this kind of job, is called an InputStream or an OutputStream.
Whatever method you have that takes a File? That's the end of the road. A File is a file. You can't fake it. But, talk to the developers, or check for alternate methods, because there is absolutely no reason anything in java that does data processing requires a File. It should be requiring an InputStream or possibly a Reader. Or perhaps even there is a method that gives you an OutputStream or Writer. All of these things are fine - they are abstractions that lets you just send data to it, from a file, a network connection, or made up whole cloth, which is what you want.
Once you have one of those, it's trivial. For example:
String text = "The Text you wanted to store in a fake file";
byte[] data = text.getBytes(StandardCharsets.UTF_8);
ByteArrayInputStream in = new ByteArrayInputStream(data);
whateverSystemYouNeedToSendThisTo.send(in);
Or for example:
String text = "The Text you wanted to store in a fake file";
byte[] data = text.getBytes(StandardCharsets.UTF_8);
try (var out = whateverSystemYouNeedToSendThisTo.getOUtputStream()) {
out.write(data);
}
Take a look at the function below:
Imports
import com.google.common.io.Files;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import java.io.*;
import java.nio.file.Paths;
Function:
#GetMapping(value = "/getFile", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
private ResponseEntity<byte[]> getFile() throws IOException {
File tempDir = Files.createTempDir();
File file = Paths.get(tempDir.getAbsolutePath(), "fileName.txt").toFile();
String data = "Some data"; //
try (FileWriter fileWriter = new FileWriter(file)) {
fileWriter.append(data).flush();
} catch (Exception ex) {
ex.printStackTrace();
}
byte[] zippedData = toByteArray(new FileInputStream(file));
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentDisposition(ContentDisposition.builder("attachment").filename("file.txt").build());
httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
httpHeaders.setContentLength(zippedData.length);
return ResponseEntity.ok().headers(httpHeaders).body(zippedData);
}
public static byte[] toByteArray(InputStream in) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] buffer = new byte[in.available()];
int len;
// read bytes from the input stream and store them in buffer
while ((len = in.read(buffer)) != -1) {
// write bytes from the buffer into output stream
os.write(buffer, 0, len);
}
return os.toByteArray();
}
In a nutshell, you want to store data in memory. Basic building block for this is array of bytes - byte[].
In JDK there are two classes to connect IO world with byte array - ByteArrayInputStream and ByteArrayOutputStream.
Rest is just same, as when dealing with files.
Example 1
#GetMapping(value = "/image")
public #ResponseBody byte[] getImage() throws IOException {
InputStream in = getClass()
.getResourceAsStream("/com/baeldung/produceimage/image.jpg");
return IOUtils.toByteArray(in);
}
Example 2:
#GetMapping("/get-image-dynamic-type")
#ResponseBody
public ResponseEntity<InputStreamResource> getImageDynamicType(#RequestParam("jpg") boolean jpg) {
MediaType contentType = jpg ? MediaType.IMAGE_JPEG : MediaType.IMAGE_PNG;
InputStream in = jpg ?
getClass().getResourceAsStream("/com/baeldung/produceimage/image.jpg") :
getClass().getResourceAsStream("/com/baeldung/produceimage/image.png");
return ResponseEntity.ok()
.contentType(contentType)
.body(new InputStreamResource(in));
}
Ref: https://www.baeldung.com/spring-controller-return-image-file

How to properly open a png file

I am trying to attach a png file. Currently when I sent the email, the attachment is 2x bigger than the file should be and an invalid png file. Here is the code I currently have:
import com.sendgrid.*;
Attachments attachments = new Attachments();
String filePath = "/Users/david/Desktop/screenshot5.png";
String data = "";
try {
data = new String(Files.readAllBytes(Paths.get(filePath)));
} catch (IOException e) {
}
byte[] encoded = Base64.encodeBase64(data.getBytes());
String encodedString = new String(encoded);
attachments.setContent(encodedString);
Perhaps I am encoding the data incorrectly? What would be the correct way to 'get' the data to attach it?
With respect, this is why Python presents a problem to modern developers. It abstracts away important concepts that you can't fully understand in interpreted languages.
First, and this is a relatively basic concept, but you can't convert arbitrary byte sequences to a string and hope it works out. The following line is your first problem:
data = new String(Files.readAllBytes(Paths.get(filePath)));
EDIT: It looks like the library you are using expects the file to be base64 encoded. I have no idea why. Try changing your code to this:
Attachments attachments = new Attachments();
String filePath = "/Users/david/Desktop/screenshot5.png";
try {
byte[] encoded = Base64.encodeBase64(Files.readAllBytes(Paths.get(filePath)));
String encodedString = new String(encoded);
attachments.setContent(encodedString);
} catch (IOException e) {
}
The only issue you were having is that you were trying to represent arbitrary bytes as a string.
Take a look at the Builder class in the repository here. Example:
FileInputStream fileContent = new FileInputStream(filePath);
Attachments.Builder builder = new Attachments.Builder(fileName, fileContent);
mail.addAttachments(builder.build());

Image Not converting properly from tiff to jpg [duplicate]

recently i'm facing problem when try to display an image file. Unfortunately, the image format is TIFF format which not supported by major web browser (as i know only Safari support this format). Due to certain constraint, i have to convert this format to others format that supported by major browser. However, it bring a lots of problem for me when i try to converting the format.
I had search through the web and although there been posted similar issue in this link How do I convert a TIF to PNG in Java?" but i can't have the result as it proposed..
Therefore i raise this Question again to wish that can have better explanation and guideline from you all..
There were few issue i'm faced during go through with the solution that proposed:
1) According to the answer that proposed by Jonathan Feinberg, it need to install JAI and JAI/ImageIO.
However, after i installed both of them i still couldn't import the file in Netbean 7.2. NetBean 7.2 remain propose import default imageIO library.
2) when i'm using default ImageIO library Read method, it will return NULL value and i cannot continue to proceed.
3) I also tried others method such as convert TIFF file to BIN File by using BufferedOutputStream method but the result file is greater than 11 MB which is too large to load and end up loading failed.
if (this.selectedDO != null) {
String tempDO = this.selectedDO.DONo;
String inPath = "J:\\" + tempDO + ".TIF";
String otPath = "J:\\" + tempDO + ".bin";
File opFile = new File(otPath);
File inFile = new File(inPath);
BufferedInputStream input = null;
BufferedOutputStream output = null;
try {
input = new BufferedInputStream(new FileInputStream(inPath), DEFAULT_BUFFER_SIZE);
output = new BufferedOutputStream(new FileOutputStream(otPath), DEFAULT_BUFFER_SIZE);
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
} finally {
try {
output.flush();
output.close();
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Hence, hope that can get help and advise from you all so that i can convert TIFF format to other format such as JPEG/PNG.
Had gone through some study and testing, found a method to convert TIFF to JPEG and sorry for pending so long only uploaded this answer.
SeekableStream s = new FileSeekableStream(inFile);
TIFFDecodeParam param = null;
ImageDecoder dec = ImageCodec.createImageDecoder("tiff", s, param);
RenderedImage op = dec.decodeAsRenderedImage(0);
FileOutputStream fos = new FileOutputStream(otPath);
JPEGEncodeParam jpgparam = new JPEGEncodeParam();
jpgparam.setQuality(67);
ImageEncoder en = ImageCodec.createImageEncoder("jpeg", fos, jpgparam);
en.encode(op);
fos.flush();
fos.close();
otPath is the path that you would like to store your JPEG image.
For example: "C:/image/abc.JPG";
inFile is the input file which is the TIFF file
At least this method is workable to me. If there is any other better method, kindly share along with us.
EDIT: Just want to point out an editing in order to handle multipage tiff. Obviously you also have to handle the different names for the resulting images:
for (int page = 0; page < dec.getNumPages(); page++) {
RenderedImage op = dec.decodeAsRenderedImage(page );
...
}
Add dependency
<dependency>
<groupId>com.github.jai-imageio</groupId>
<artifactId>jai-imageio-core</artifactId>
<version>1.3.1</version> </dependency>
https://mvnrepository.com/artifact/com.github.jai-imageio/jai-imageio-core
https://mvnrepository.com/artifact/com.github.jai-imageio/jai-imageio-core/1.3.1
Coding
final BufferedImage tif = ImageIO.read(new File("test.tif"));
ImageIO.write(tif, "png", new File("test.png"));
In case of many pages, working following:
add dependency:
<dependency>
<groupId>com.github.jai-imageio</groupId>
<artifactId>jai-imageio-core</artifactId>
<version>1.4.0</version>
</dependency>
use following Java8 code
public void convertTiffToPng(File file) {
try {
try (InputStream is = new FileInputStream(file)) {
try (ImageInputStream imageInputStream = ImageIO.createImageInputStream(is)) {
Iterator<ImageReader> iterator = ImageIO.getImageReaders(imageInputStream);
if (iterator == null || !iterator.hasNext()) {
throw new RuntimeException("Image file format not supported by ImageIO: " + file.getAbsolutePath());
}
// We are just looking for the first reader compatible:
ImageReader reader = iterator.next();
reader.setInput(imageInputStream);
int numPage = reader.getNumImages(true);
// it uses to put new png files, close to original example n0_.tiff will be in /png/n0_0.png
String name = FilenameUtils.getBaseName(file.getAbsolutePath());
String parentFolder = file.getParentFile().getAbsolutePath();
IntStream.range(0, numPage).forEach(v -> {
try {
final BufferedImage tiff = reader.read(v);
ImageIO.write(tiff, "png", new File(parentFolder + "/png/" + name + v + ".png"));
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
If your target is Android, you could try this great Java library on Github that provides many utilities for handling, opening, and writing .tiff files.
A simple example from that Git showng how to convert TIFF to JPEG:
TiffConverter.ConverterOptions options = new TiffConverter.ConverterOptions();
//Set to true if you want use java exception mechanism
options.throwExceptions = false;
//Available 128Mb for work
options.availableMemory = 128 * 1024 * 1024;
//Number of tiff directory to convert;
options.readTiffDirectory = 1;
//Convert to JPEG
TiffConverter.convertTiffJpg("in.tif", "out.jpg", options, progressListener);
First, take a look to What is the best java image processing library/approach?. For your code you can use
javax.imageio.ImageIO.write(im, type, represFile);
like you can see in write an image to file example.

Can't read text file and can't find a solution [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I've tried many methods of reading files and I have found that none of them work. I am not using the default libraries. I'm using a framework that is found from here
I'm trying to read it and insert it line by line into a String array. Every method I've tried requires a Context, but because this is not initialized the same way as a default android application, it doesn't have a context to use getAssets. Is there any other way of reading a text file?
I tried using this set of code, but it didn't work because it required assets.
InputStream iS;
resources = AndroidGame.resources;
if (loadFromRawFolder) {
int rID = resources.getIdentifier("raw/store_app", "raw", "com.cciamlazy.pixunited");
iS = resources.openRawResource(rID);
} else {
iS = resources.getAssets().open(inFile);
}
byte[] buffer = new byte[iS.available()];
iS.read(buffer);
ByteArrayOutputStream oS = new ByteArrayOutputStream();
oS.write(buffer);
oS.close();
iS.close();
This code gives me errors and the resources != null. Gives me the error:
android.content.res.Resources$NotFoundException: Resource ID #0x0
Full class code
package com.cciamlazy.pixunited;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import android.app.Activity;
import android.content.res.Resources;
public class MapLoader extends Activity {
private static Resources resources;
public MapLoader() {
resources = getResources();
}
public static String LoadFile(String fileName, boolean loadFromRawFolder) throws IOException {
// Create a InputStream to read the file into
InputStream iS;
if (loadFromRawFolder) {
// get the resource id from the file name
// int rID = resources.getIdentifier(fileName, null, null);
int rID = resources.getIdentifier("raw/store_app", "raw",
"com.cciamlazy.activity");
// get the file as a stream
iS = resources.openRawResource(rID);
} else {
// get the file as a stream
iS = resources.getAssets().open(fileName);
}
// create a buffer that has the same size as the InputStream
byte[] buffer = new byte[iS.available()];
// read the text file as a stream, into the buffer
iS.read(buffer);
// create a output stream to write the buffer into
ByteArrayOutputStream oS = new ByteArrayOutputStream();
// write this buffer to the output stream
oS.write(buffer);
// Close the Input and Output streams
oS.close();
iS.close();
// return the output stream as a String
return oS.toString();
}
}
Hope this helps.....
add these two lines to your activity
private static Resources resources;
resources = getResources();
After that add this method.
public static String LoadFile(String fileName, boolean loadFromRawFolder)
throws IOException {
// Create a InputStream to read the file into
InputStream iS;
if (loadFromRawFolder) {
// get the resource id from the file name
// int rID = resources.getIdentifier(fileName, null, null);
int rID = resources.getIdentifier("raw/store_app", "raw",
"com.example.activity");
// get the file as a stream
iS = resources.openRawResource(rID);
} else {
// get the file as a stream
iS = resources.getAssets().open(fileName);
}
// create a buffer that has the same size as the InputStream
byte[] buffer = new byte[iS.available()];
// read the text file as a stream, into the buffer
iS.read(buffer);
// create a output stream to write the buffer into
ByteArrayOutputStream oS = new ByteArrayOutputStream();
// write this buffer to the output stream
oS.write(buffer);
// Close the Input and Output streams
oS.close();
iS.close();
// return the output stream as a String
return oS.toString();
}

JAVA encode/decode base 64 and render it on browser or save it to file

I am sending an image after base64 encoding from my JSP to a servlet using AJAX. At the servlet side, I am trying to decode and save it to either a file or render to a browser.
I am getting an empty image. Here is my servlet side code
String imageStr = request.getParameter("image");
byte[] decoded = Base64.decodeBase64(imageStr);
String path = "D:\\myImage.png";
try {
OutputStream out1 = new BufferedOutputStream(new FileOutputStream(path));
out1.write(decoded);
} finally {
}
I get a the image, but its empty.
Try closing the stream, it should flush all buffered data:
String imageStr = request.getParameter("image");
byte[] decoded = Base64.decodeBase64(imageStr);
String path = "D:\\myImage.png";
OutputStream out1 = null;
try {
out1 = new BufferedOutputStream(new FileOutputStream(path));
out1.write(decoded);
} finally {
if (out1 != null) {
*out1.close();*
}
}
And make sure the decoded array really contains some data.

Categories