I have some troubles with loading a image out of a war file. My function for this is the following:
private String printResource(ResourceBean resource) throws IOException {
URLConnection connection = getServerURL(resource.getPath()).openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder response = new StringBuilder();
String inputLine;
while ((inputLine = in.readLine()) != null)
response.append(inputLine).append("\n");
in.close();
return response.toString();
}
The return value of this function will be written directly in the webpage. My issue is the following. The image is not displayed and if I download and open it. the program tell me, that the image is invalid or damaged.
I have no idea where the problem could be, I would be really grateful for an answer.
EDIT:
I have added some changes to the function:
private String printResource(ResourceBean resource, HttpServletResponse response) throws IOException {
URL url = getServerURL(resource.getPath());
if (resource.getType().equals("pic")) {
masterLogger.debug("Resource is a pic, special treatment");
BufferedImage img = ImageIO.read(url);
File f = new File(resource.getId());
ImageIO.write(img, "jpg", f);
FileOutputStream fis = new FileOutputStream(f);
return fis.toString();
} else {
URLConnection connection = getServerURL(resource.getPath()).openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder responseText = new StringBuilder();
String inputLine;
while ((inputLine = in.readLine()) != null)
responseText.append(inputLine).append("\n");
in.close();
return responseText.toString();
}
}
Now I get a NullPointer at the ImageIO.write() line 1538.
More informaiton:
I load a jpg from my resources in the war file
The URL is correct, oterwise the first line would throw a NullPointerException.
Use:
BufferedImage img = ImageIO.read(url);
Example:
URLConnection connection = new URL(url).openConnection();
BufferedImage img = ImageIO.read(connection.getInputStream());
ImageIO.write(img, "jpg", new File("downloaded_1.jpg"));
ImageIO.write(img, "png", new File("downloaded_2.png"));
or you can write to the servlet response (providing correct request and response properties) or ByteArrayOutputStream instance
If it's from war best way to get the path is through ServletContext ex: InputStream input = getServletContext().getResourceAsStream(path);
Related
I have one REST URL which if I use in postman it gives me image in response. Now, I'm trying to see the same thing with JAVA code in Eclipse. (I'm looking for either saving image file or showing with JFrame or Applet etc.)
String url = "https://test-api.com/v1/abc.jpg";
// Creating URL Connection
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// Defining the request method. It can be GET, POST, PUT, DELETE
con.setRequestMethod("GET");
// Getting the HTTP Response code like 200, 404 etc.
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url + "\n");
System.out.println("Response Code : " + responseCode + "\n");
// Saving response in the Stringbuffer
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
byte bytes[] = String.valueOf(response).getBytes();
InputStream inS = new ByteArrayInputStream(bytes);
int width = 963; //width of the image
int height = 640; //height of the image
BufferedImage image = null;
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
BufferedImage bImageFromConvert = ImageIO.read(inS);
When I run the code, I get the exception like below.
javax.imageio.IIOException: Invalid JPEG file structure: two SOI markers
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImageHeader(Native Method)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readNativeHeader(JPEGImageReader.java:628)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.checkTablesOnly(JPEGImageReader.java:347)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.gotoImage(JPEGImageReader.java:495)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readHeader(JPEGImageReader.java:621)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1078)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1058)
at javax.imageio.ImageIO.read(ImageIO.java:1448)
at javax.imageio.ImageIO.read(ImageIO.java:1352)
Response code comes 200. So, not sure what I'm doing wrong here. Why ImageIO cannot read the inputstream and picking up two SOI marker.
To show an image on the browser using jax-rs you can use this method with the hypothese that you have images folder under resources in your classpath :
#GET
#Path("image")
#Produces({"image/jpeg"})
public Response getImage() {
BufferedImage image = null;
byte[] imageData = null;
try {
//System.out.println("chemin courant : " + ClassLoader.getSystemClassLoader().
// getResource(".").getPath());
image = ImageIO.read(ClassLoaderTestResource.class
.getResourceAsStream("/images/yourimage.jpg"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
imageData = baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("image : "+ image);
System.out.println("Image data : "+ imageData);
return Response.ok(new ByteArrayInputStream(imageData)).build();
}
so if you call http://localhost:8080/image for example you will have your image in the browser.
I've been trying to send a base64 image using java to NodeJS API, after working and searching for hours I could not know what might cause the following problem, the problem as following:
After logging the base64 image in nodejs I see all + chars replaced by space
Here's a part of the original base64 in Java
f8A0NH2qH+/+hooouAfaof7/wCho+1Q/
and here's is a part of the received image in NodeJS
f8A0NH2qH / hooouAfaof7/wCho 1Q/
I've tried to send an image via POSTMAN and no problem at all.
All steps as following:
1- I am converting an image to base64 using the following snippet
public static String imgToBase64String(final RenderedImage img, final String formatName) {
final ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
ImageIO.write(img, formatName, Base64.getEncoder().wrap(os));
return os.toString(StandardCharsets.ISO_8859_1.name());
} catch (final IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
public static BufferedImage base64StringToImg(final String base64String) {
try {
return ImageIO.read(new ByteArrayInputStream(Base64.getDecoder().decode(base64String)));
} catch (final IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
And to take screenshot
final Robot robot = new Robot();
final Rectangle r = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
final BufferedImage bi = robot.createScreenCapture(r);
final String base64String = Base64Converter.imgToBase64String(bi, "jpg");
2- I am using Gson library to stringify object
3- I am using bodyParser in NodeJS
4- Sending HTTP request as:
public static void sendPOST(String image) throws Exception {
String POST_PARAMS = "screenShotData";
URL obj = new URL(POST_URL);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setConnectTimeout(5000); // 5 seconds
con.setReadTimeout(5000); // 5 seconds
Gson gson = new Gson();
Http.ScreenShot screenShot = new ScreenShot(); // This is just a class with a string property
screenShot.setImage(image);
POST_PARAMS += gson.toJsonTree(screenShot).getAsJsonObject();
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
byte[] outputBytesArray = POST_PARAMS.getBytes();
os.write(outputBytesArray);
os.flush();
os.close();
int responseCode = con.getResponseCode();
System.out.println("POST Response Code :: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) { //success
BufferedReader in = new BufferedReader(new InputStreamReader(
con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
Object responseObject = gson.fromJson(response.toString(), Object.class);
System.out.println("Res: " + responseObject);
} else {
System.out.println(con.getResponseMessage());
}
}
In URL encoded text, the + character means a space character. For example,
https://example.com/?s=nodejs+bodyparser
sends the s parameter with the value
nodejs bodyparser
(notice the space).
When you do an ordinary form post (the kind browsers do) you use the application/x-www-form-urlencoded data type, meaning the payload of your POST operation looks like a query string. I think you are passing a JSON object as a text string without url-encoding it.
You probably want to use the application/json data type instead. nodejs's body parser detects, from your Content-type header, that it's JSON and parses it correctly.
Try this. (not debugged, sorry.)
string payload = gson.toJsonTree(screenShot).getAsJsonObject();
byte[] outputBytesArray = payload.getBytes();
con.setRequestProperty("Content-Type", "application/json");
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
os.write(outputBytesArray);
os.flush();
os.close();
You forgot to close the wrapped Base64 encoder stream. Only if you close it the end of the base64 encoded data can be written:
public static String imgToBase64String(final RenderedImage img, final String formatName) {
final ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
try (OutputStream wrapped = Base64.getEncoder().wrap(os)) {
ImageIO.write(img, formatName, wrapped);
}
return os.toString(StandardCharsets.ISO_8859_1.name());
} catch (final IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
I had faced this issue, but I had no authority to change in class or something else.
I had just simply replaced space with +, in most of the cases it was working.
I'm trying to upload an image with JAVA to a self-hosted ActiveCollab.
I have made a couple of tests and this one seems for me like the most solid of them by far. Anyway, when I try to run it, I get code 200-OK and an empty array as a response. .
public static void main(String args[]) throws IOException {
URL url = new URL("<SITE>/api/v1/upload-files");
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setDoOutput(true);
c.setRequestProperty("Content-Type", "multipart/form-data");
c.setRequestProperty("X-Angie-AuthApiToken", "<TOKEN>");
JSONArray array = new JSONArray();
array.put("/test.png");
array.put("image/png");
OutputStream out = c.getOutputStream();
out.write(array.toString().getBytes());
out.flush();
out.close();
BufferedReader buf = new BufferedReader(new InputStreamReader(c.getInputStream()));
StringBuffer response = new StringBuffer();
String line;
while (null != (line = buf.readLine())) {
response.append(line);
}
JSONArray message = new JSONArray(response.toString());
System.out.println(message);
}
In the API documentation I should get a filled json array as a response. Actually I don't know at what I'm missing.
Finally I solved it! As #StephanHogenboom said, the problem were in multipart/form-data, the parameters had to be introduced there and not via JSONArray. I didn't find so much information about how to work with multipart in java.net but at least I've found a deprecaded but functional way to the the job.
public static void main(String args[]) throws IOException {
URL url = new URL("<SITE>/api/v1/upload-files");
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setDoOutput(true);
c.setRequestMethod("POST");
c.setRequestProperty("X-Angie-AuthApiToken", "<TOKEN>");
File file = new File("/1.png");
FileBody fileBody = new FileBody(file, "image/png");
MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.STRICT);
multipartEntity.addPart("file", fileBody);
c.setRequestProperty("Content-Type", multipartEntity.getContentType().getValue());
OutputStream out = c.getOutputStream();
multipartEntity.writeTo(out);
out.close();
BufferedReader buf = new BufferedReader(new InputStreamReader(c.getInputStream()));
StringBuffer response = new StringBuffer();
String line;
while (null != (line = buf.readLine())) {
response.append(line);
}
JSONArray message = new JSONArray(response.toString());
System.out.println(message);
}
Actually it works for me, but if someone can give me ideas about how improve it would be great!
I am trying to download a PDF file with HttpClient, it is downloading the PDF file but pages are blank. I can see the bytes on console from response if I print them. But when I try to write it to file it is producing a blank file.
FileUtils.writeByteArrayToFile(new File(outputFilePath), bytes);
However the file is showing correct size of 103KB and 297KB as expected but its just blank!!
I tried with Output stream as well like:
FileOutputStream fileOutputStream = new FileOutputStream(outFile);
fileOutputStream.write(bytes);
Also tried to write with UTF-8 coding like:
Writer out = new BufferedWriter( new OutputStreamWriter(
new FileOutputStream(outFile), "UTF-8"));
String str = new String(bytes, StandardCharsets.UTF_8);
try {
out.write(str);
} finally {
out.close();
}
Nothing is working for me. Any suggestion is highly appreciated..
Update: I am using DefaultHttpClient.
HttpGet httpget = new HttpGet(targetURI);
HttpResponse response = null;
String htmlContents = null;
try {
httpget = new HttpGet(url);
response = httpclient.execute(httpget);
InputStreamReader dataStream=new InputStreamReader(response.getEntity().getContent());
byte[] bytes = IOUtils.toByteArray(dataStream);
...
You do
InputStreamReader dataStream=new InputStreamReader(response.getEntity().getContent());
byte[] bytes = IOUtils.toByteArray(dataStream);
As has already been mentioned in comments, using a Reader class can damage binary data, e.g. PDF files. Thus, you should not wrap your content in an InputStreamReader.
As your content can be used to construct an InputStreamReader, though, I assume response.getEntity().getContent() returns an InputStream. Such an InputStream usually can be directly used as IOUtils.toByteArray argument.
So:
InputStream dataStream=response.getEntity().getContent();
byte[] bytes = IOUtils.toByteArray(dataStream);
should already work for you!
Here is a method I use to download a PDF file from a specific URL. The method requires two string arguments, an url string (example: "https://www.ibm.com/support/knowledgecenter/SSWRCJ_4.1.0/com.ibm.safos.doc_4.1/Planning_and_Installation.pdf") and a destination folder path to download the PDF file (or whatever) into. If the destination path does not exist within the local file system then it is automatically created:
public boolean downloadFile(String urlString, String destinationFolderPath) {
boolean result = false; // will turn to true if download is successful
if (!destinationFolderPath.endsWith("/") && !destinationFolderPath.endsWith("\\")) {
destinationFolderPath+= "/";
}
// If the destination path does not exist then create it.
File foldersToMake = new File(destinationFolderPath);
if (!foldersToMake.exists()) {
foldersToMake.mkdirs();
}
try {
// Open Connection
URL url = new URL(urlString);
// Get just the file Name from URL
String fileName = new File(url.getPath()).getName();
// Try with Resources....
try (InputStream in = url.openStream(); FileOutputStream outStream =
new FileOutputStream(new File(destinationFolderPath + fileName))) {
// Read from resource and write to file...
int length = -1;
byte[] buffer = new byte[1024]; // buffer for portion of data from connection
while ((length = in.read(buffer)) > -1) {
outStream.write(buffer, 0, length);
}
}
// File Successfully Downloaded");
result = true;
}
catch (MalformedURLException ex) { ex.printStackTrace(); }
catch (IOException ex) { ex.printStackTrace(); }
return result;
}
I'm calling a script that gives me a binary file (12345.cl), with binary data. The script is done, and it's working, if I paste it on the navigator I get the binary file.
Now I have a problem: How I transform the response of the script into a binary resource to use it in my app?
For the moment, i have this code:
public void decodeStream( String mURL ){
BufferedInputStream bis = new BufferedInputStream(new URL(mURL).openStream(), BUFFER_IO_SIZE);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(baos, BUFFER_IO_SIZE);
copy(bis, bos);
bos.flush();
Then, I have a BufferedOutputStream with the response, but I don't know how to transform it into a binary resource to use it
I need to obtain a datainputstream with the file but I don't know how to achieve it
You can use following code:
public void decodeStream( String mURL, String ofile ) throws Exception {
InputStream in = null;
FileOutputStream out = null;
try {
URL url = new URL(mURL);
URLConnection urlConn = url.openConnection();
in = urlConn.getInputStream();
out = new FileOutputStream(ofile);
int c;
byte[] b = new byte[1024];
while ((c = in.read(b)) != -1)
out.write(b, 0, c);
} finally {
if (in != null)
in.close();
if (out != null)
out.close();
}
}