How to print/read image from REST API call using JAVA - java

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.

Related

Upload image to server efficiently in Android

I have an app that needs to send an image to a server. Right now I'm doing it like this:
//We have a variable "image" that is the Bitmap that we want to send
File imagesFolder = new File(getCacheDir(), "images");
File file = null;
try {
if(imagesFolder.exists() || imagesFolder.mkdirs()) {
file = new File(imagesFolder, "input.jpg");
FileOutputStream stream = new FileOutputStream(file);
//checkWifiOnAndConnected returns true if wifi is on and false if mobile data is being used
image.compress(Bitmap.CompressFormat.JPEG, checkWifiOnAndConnected() ? 90 : 80, stream);
stream.flush();
stream.close();
}
} catch (IOException e) {
Log.d("Error", "IOException while trying to write file for sharing: " + e.getMessage());
}
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addPart("file", new FileBody(file));
HttpEntity entity = builder.build();
URL url = new URL(serverUrl);
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(40000);
conn.setConnectTimeout(40000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setFixedLengthStreamingMode(entity.getContentLength());
conn.addRequestProperty(entity.getContentType().getName(), entity.getContentType().getValue());
OutputStream os = conn.getOutputStream();
entity.writeTo(os);
os.close();
conn.connect();
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK)
Log.e("UPLOAD", "HTTP 200 OK.");
It works, but it's kinda slow, specially when using mobile data (obviously). And I would like to know if there's a more efficient and faster way to send this image.

Sending base64 image via http request in Java miss up some chars

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.

Sending image from java client to python server

I'm new to java and I've been stuck on this problem for the last few days. I'm sending an image from a java client to a python server. I'm getting a 200 request, meaning the connection is being made. But the image is not being read on the server side. I've included the code - any help would be great.
Server Code
def index(request):
data = {"POST REQUEST, INSIDE INDEX, NO URL OR IMAGE SENT": False}
if request.method == "GET":
return HttpResponse("GET REQUEST WORKS. RR.")
if request.method == "POST":
# check to see if an image was uploaded
if request.FILES.get("image", None) is not None:
# grab the uploaded image
image = request.FILES["image"]
# otherwise, assume that a URL was passed in
else:
# grab the URL from the request
url = request.POST.get("url", None)
# if the URL is None, then return an error
if url is None:
return HttpResponse("no URL is specified")
# load the image and convert
image = _grab_image(url=url)
req = image
arr = np.asarray(bytearray(req.read()), dtype=np.uint8)
img = cv2.imdecode(arr,-1) # 'load it as it is'
Server = True
Student_Answers = []
image = doc_Scan(img)
if (image == "ERROR"):
return HttpResponse("TAKE ANOTHER PICTURE")
else:
images = crop_answer2(image)
for i in range(0,8):
ans = images[i]
Answer = Input_Image(ans,Server)
print ('Final Answer = ', Answer)
Student_Answers.append(Answer)
Results, score = mark_paper(Server,Student_Answers)
Worded_Respose = "The Student got ", score, " correct"
return HttpResponse(Results, content_type="application/json")
else:
return HttpResponse("NO POST REQUEST")
Client Code
public static void main(String [] args) throws Exception{
String url = "http://########";
// 2. create obj for the URL class
URL obj = new URL(url);
// 3. open connection on the url
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
try {
System.out.println("Reading image from disk. ");
img = ImageIO.read(new File("image.jpg"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", baos);
baos.flush();
byte[] bytes = baos.toByteArray();
baos.close();
System.out.println("Sending image to server. ");
OutputStream out = con.getOutputStream();
DataOutputStream image = new DataOutputStream(out);
image.writeInt(bytes.length);
image.write(bytes, 0, bytes.length);
System.out.println("Image sent to server. ");
image.close();
// close the output stream
out.close();
}catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
soc.close();
}
// define object for the reply from the server
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
//Get response from server
int responseCode = con.getResponseCode();
System.out.println("Response Code : " + responseCode);
// read in the response from the server
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
System.out.println(inputLine);
}
// close the input stream
in.close();
}
}

saving file as .pdf as recieved in http response error

For my project i need to download a pdf file from google drive using java
I get my httpresponse code 200 and by using following method i store it in abc.pdf file
String url = "https://docs.google.com/uc?id="+fileid+"&export=download";
URL obj = new URL(url);
HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
// optional default is GET
conn.setRequestMethod("GET");
//add request header
conn.setRequestProperty("User-Agent", USER_AGENT);
int responseCode = conn.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String inputLine;
OutputStream f0 = new FileOutputStream("C:\\Users\\Darshil\\Desktop\\abc.pdf",true);
while ((inputLine = in.readLine()) != null) {
//System.out.println(inputLine);
byte b[]=inputLine.getBytes();
//System.out.println(b);
f0.write(b);
}
in.close();
f0.close();
But when i try to open abc.pdf in my adobe reader x i get following error:
There was an error opening this document.The file is damaged and could not be repaired
You seem to be directly accessing the Google drive using Raw HTTP requests.
You may be better of using the Google Drive SDK. This link contains good examples to address the use cases you state in your question.
However if you do want to stick to your technique then you should not be using a BufferedReader.readLine(). This is because the PDF file is a binary finally that would depend upon the correct byte sequences to be preserved in order to be read correctly by the PDF reader software. Hopefully the below technique should help you:
//read in chunks of 2KB
byte[] buffer = new byte[2048];
int bytesRead = 0;
try(InputStream is = conn.getInputStream())
{
try(DataOutputStream os = new DataOutputStream(new FileOutputStream("file.pdf"))
{
while((bytesRead = is.read(buffer)) != -1)
{
os.write(buffer, 0, bytesRead);
}
}
}
catch(Exception ex)
{
//handle exception
}
Note that I am using the try-with-resources statement in Java 7
Hope this helps.

Loade image from war

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);

Categories

Resources