Copying Image from URL to HTTP URL - java

Someone is providing a S3 Presigned URL so that I can upload my images to that link. All my images are on the website. Is there a way in JAVA to copy the image URL to the new URL provided ?
I am trying to do this. Seems like an overkill
try {
// Get Image from URL
URL urlGet = new URL("http://something.com/something.png");
BufferedImage image = ImageIO.read(urlGet);
//for png
ImageIO.write(image, "png",new File("/something.png"));
// for jpg
//ImageIO.write(image, "jpg",new File("/something.jpg"));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(image, "png", outputStream);
outputStream.flush();
byte[] imageInBytes = outputStream.toByteArray();
outputStream.close();
URL url = new URL(putUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod(HttpMethod.PUT);
connection.setRequestProperty(HttpHeaders.CONTENT_TYPE, PNG_MIME_TYPE);
OutputStream stream = connection.getOutputStream();
try {
stream.write(imageInBytes);
} finally {
stream.close();
connection.disconnect();
}
switch (connection.getResponseCode()) {
case HttpURLConnection.HTTP_OK:
return "";
default:
break;
}
} catch (Exception e) {
log.error("Exception occured", e);
throw e;
}

There would be no point converting to BufferedImage and back for the copy when you can preserve the byte stream of the original files. The first part can be replaced with simple call to extract the bytes off your website:
byte[] imageInBytes = read(urlGet);
Where read() is:
private static byte[] read(URL url) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(16*1024);
try (var in = url.openStream()) {
in.transferTo(out);
}
return out.toByteArray();
}
If you use JDK11 onwards you could try the HttpClient class for the GET and POSTs, for example this does same as above if passing it urlGet.toURI():
private static byte[] read(URI uri) throws IOException, InterruptedException
{
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder().uri(uri).build();
var resp = client.send(request, BodyHandlers.ofByteArray());
return resp.body();
}

Related

How to GET image from url via API in java?

This should be an easy learning task but something went wrong:
Use API request to get image from some link and check it is in Base64 standard.
private static void getRequest() throws IOException {
URL url = new URL("http://apimeme.com/meme?meme=Alarm-Clock&top=Top+text&bottom=Bottom+text");
InputStream is = (InputStream) url.openStream();
FileInputStream imageInFile = new FileInputStream(is.toString());
byte imageData[] = new byte[2048];
imageInFile.read(imageData);
System.out.println(isBase64(imageInFile.toString()));
}
static boolean isBase64(String path) {
try {
Base64.getDecoder().decode(path);
return true;
} catch(IllegalArgumentException e) {
return false;
}
}
Right now problem is on line
InputStream is = (InputStream) url.openStream();
Server sends 403. How to fix this? Method isBase64 should work but the program doesn't reach this line.
Your need 3 header for avoid http 403 error code
private static void getRequest() throws IOException {
URL url = new URL("http://apimeme.com/meme?meme=Alarm-Clock&top=Top+text&bottom=Bottom+text");
URLConnection is = url.openConnection();
is.setRequestProperty("Host", "apimeme.com");
is.setRequestProperty("Cookie", "*");
is.setRequestProperty("User-Agent", "*");
byte[] imageData = new byte[2048];
File downloadFile = new File("download.png");
FileOutputStream outputStream = new FileOutputStream(downloadFile);
int read;
while ((read = is.getInputStream().read(imageData)) != -1) {
outputStream.write(imageData, 0, read);
}
outputStream.close();
System.out.println(isBase64(downloadFile.getAbsolutePath()));
}
403 is means that you do not have permission to view this URL. You cannot do anything to fix this client side, even authorization would not help (if the ressource required authorization, the server would send 401 instead). So to fix the issue, whoever is in charge of the web server delivering the URL you're trying to access will have to fix this - if they think you should have access.

Convert outputstream byte array into string

I am trying to send a file path to a Rest Api through DataOutputStream. DataOutputStream converts string into bytes and I am having trouble converting the byte back to desired String.
Here is my method that calls Api
private void sendFilePath(String filePath) {
try {
URL url = new URL("http://localhost:8080/uploadExcelFile");
HttpURLConnection connection = (HttpURLConnection)
url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-
form-urlencoded");
connection.setDoOutput(true);
connection.setDoInput(true);
DataOutputStream outputStream = new
DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(filePath);
outputStream.flush();
outputStream.close();
connection.getResponseCode();
} catch (IOException e) {
e.printStackTrace();
}
}
and here is controller method aka Api
#PostMapping("/uploadExcelFile")
public HttpStatus uploadFile(#RequestBody byte[] byteFilePath) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(byteFilePath);
String filePath = baos.toString();
Workbook workbook = WorkbookFactory.create(new File(filePath));
List<StudentModel> students = studentService.convertExcelToData(workbook);
return studentHandler.createStudent(students);
} catch (InvalidFormatException | IOException e) {
e.printStackTrace();
return HttpStatus.BAD_REQUEST;
}
}
The filepath argument in sendFilePath() is D:\Projects\AutoFeeChallan\Aptech Student Records.xlsx
while the one I get in uploadApi after converting to String is D%3A%5CProjects%5CAutoFeeChallan%5CAptech+Student+Records.xlsx=
I want the same path in controller method as I send as argument in sendFilePath().
Can you suggest any solution or other methods to solve this problem.
By setting ,
connection.setRequestProperty("Content-Type", "application/x-www-
form-urlencoded");
you made the data URL encoded.At some point you need to urldecode it.
String filePath = java.net.URLDecoder.decode(baos.toString(), StandardCharsets.UTF_8);
Or you can change the content-type to different one.

HTTPUtils deprecated .. what do I do instead?

I need to download icons from the OpenWeatherMap website, build a URL, download the image, save it to local storage and also check to see if they already exist. HTTPUtils is underlined in red and when I looked it up, it's no longer being used. The Bitmap code was given to use by the professor.
#Override
protected String doInBackground(String... args) {
try {
URL url = new URL(TEMPS);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
InputStream inputStream = conn.getInputStream();
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(false);
XmlPullParser xpp = factory.newPullParser();
//this is what talks to the xml on the website
xpp.setInput(inputStream, "UTF-8");
while (xpp.getEventType() != XmlPullParser.END_DOCUMENT) {
if (xpp.getEventType() == XmlPullParser.START_TAG) {
if (xpp.getName().equals("temperature")) {
curr = xpp.getAttributeValue(null, "value");
//tell android to call onProgressUpdate with 25 as parameter
publishProgress(25);
min = xpp.getAttributeValue(null, "min");
publishProgress(50);
max = xpp.getAttributeValue(null, "max");
publishProgress(75);
} else if (xpp.getName().equals("weather")) {
icon = xpp.getAttributeValue(null, "icon");
}
}
xpp.next();
}
//Start of JSON reading of UV factor:
//create the network connection:
URL UVurl = new URL(UV);
HttpURLConnection UVConnection = (HttpURLConnection) UVurl.openConnection();
inputStream = UVConnection.getInputStream();
//create a JSON object from the response
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
String result = sb.toString();
//now a JSON table:
JSONObject jObject = new JSONObject(result);
double aDouble = jObject.getDouble("value");
Log.i("UV is:", ""+ aDouble);
uv = aDouble;
//*****This is where I need help
Bitmap image = null;
URL imageUrl = new URL(IMAGE);
HttpURLConnection connection = (HttpURLConnection) imageUrl.openConnection();
connection.connect();
int responseCode = connection.getResponseCode();
if (responseCode == 200) {
image = BitmapFactory.decodeStream(connection.getInputStream());
}
image = HTTPUtils.getImage(IMAGE);
FileOutputStream outputStream = openFileOutput(icon + ".png", Context.MODE_PRIVATE);
image.compress(Bitmap.CompressFormat.PNG, 80, outputStream);
outputStream.flush();
outputStream.close();
public boolean fileExistance(String weatherIcons){
File file = getBaseContext().getFileStreamPath(weatherIcons);
return file.exists();
Log.i("File name:", ""+ file);
}
FileInputStream fis = null;
try {
fis = openFileInput("C:/Users/kathy/AndroidStudioProjects/AndroidLabs/app/src/main/res/drawable");
} catch (FileNotFoundException e) {
Log.e("Download this file", e.getMessage());
}
Bitmap bm = BitmapFactory.decodeStream(fis);
publishProgress(100);
Thread.sleep(2000); //pause for 2000 milliseconds to watch the progress bar grow
} catch (Exception ex) {
}
return null;
}
While I don't really understand which package HTTPUtils comes from, I think relying on the standard classes from the JDK and Android SDK is the way to go.
try {
// Get an open Stream to the image bytes
final InputStream stream = new URL(IMAGE).openStream();
// Wrap the Stream in a buffered one for optimization purposes
// and decode it to a Bitmap
try (final InputStream bufferedInputStream = new BufferedInputStream(stream)) {
final Bitmap image = BitmapFactory.decodeStream(bufferedInputStream);
// Process the image
}
} catch (final IOException e) {
// Handle the Exception
}
You might want to extract an helper method, which simply returns the instantiated Bitmap variable.

How to throw same exception thrown by external endpoint in springboot

I'm accessing an external api and I'm expecting to get an image as response (byte[]). My method that connects to this endpoint looks like this:
private byte[] retrieveImage(String uri) {
byte[] imageBytes = null;
try {
URL url = new URL(uri);
BufferedImage bufferedImage = ImageIO.read(url);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
imageBytes = baos.toByteArray();
} catch (Exception ex) {
throw new ImageNotReadException(ex.getLocalizedMessage());
}
return imageBytes;
}
It turned out that if I pass the wrong parameters to the target endpoint I get this error message:
So basically I would like to throw the same error above but I also would like to throw an ImageNotReadException (java.lang.IllegalArgumentException: image == null! ) in case the program fails to read the image (byte[]). So basically, my method private byte[] retrieveImage(String uri) would have to throw my read image exception and the endpoint response exception.
Any tips?
Appreciate the help!
As i have commented see below options
private Response retrieveImage(String uri) {
byte[] imageBytes = null;
Response r=new Response();
try {
URL url = new URL(uri);
BufferedImage bufferedImage = ImageIO.read(url);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
imageBytes = baos.toByteArray();
r.setImage(imageBytes);
r.setStatus(1);
} catch (Exception ex) {
r.setStatus(0);
}
return r;
}
Response :
class Response{
String status;
byte[] image;
//getters setters
}
Or :
private Response retrieveImage(String uri)throws CustomException {
byte[] imageBytes = null;
try {
URL url = new URL(uri);
BufferedImage bufferedImage = ImageIO.read(url);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
imageBytes = baos.toByteArray();
} catch (Exception ex) {
throw new CustomException(ex.getLocalizedMessage());
}
return imageBytes;
}

Spring REST - Damaged/Blank File being downloaded

I am trying to create a endpoint to render/serve PDF file.
I have gone through the following links to build the API, but still facing some issues.
link 1
link 2
Following is my code :
byte[] targetArray = null;
InputStream is = null;
InputStream objectData = object.getObjectContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(objectData));
char[] charArray = new char[8 * 1024];
StringBuilder builder = new StringBuilder();
int numCharsRead;
while ((numCharsRead = reader.read(charArray, 0, charArray.length)) != -1) {
builder.append(charArray, 0, numCharsRead);
}
reader.close();
objectData.close();
object.close();
targetArray = builder.toString().getBytes();
is = new ByteArrayInputStream(targetArray);
return ResponseEntity.ok().contentLength(targetArray.length).contentType(MediaType.APPLICATION_PDF)
.cacheControl(CacheControl.noCache()).header("Content-Disposition", "attachment; filename=" + "testing.pdf")
.body(new InputStreamResource(is));
When I hit my API using postman, I am able to download PDF file but the problem is it is totally blank. What might be the issue ?
There are multiple ways to download files from server, you can use ResponseEntity<InputStreamResource>, HttpServletResponse.Below are the two methods to download.
#GetMapping("/download1")
public ResponseEntity<InputStreamResource> downloadFile1() throws IOException {
File file = new File(FILE_PATH);
InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment;filename=" + file.getName())
.contentType(MediaType.APPLICATION_PDF).contentLength(file.length())
.body(resource);
}
OR
You can use StreamingResponseBody to download large files. In this case server writes data to OutputStream at same time Browser read data which means its parallel.
#RequestMapping(value = "downloadFile", method = RequestMethod.GET)
public StreamingResponseBody getSteamingFile(HttpServletResponse response) throws IOException {
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=\"demo.pdf\"");
InputStream inputStream = new FileInputStream(new File("C:\\demo-file.pdf"));
return outputStream -> {
int nRead;
byte[] data = new byte[1024];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
System.out.println("Writing some bytes..");
outputStream.write(data, 0, nRead);
}
};
}
You can try to use apache commons IOUtils. Why reinvent wheel :)
1. Open a connection to remote server
2. Copy the inputStream to the destination file outputStream.
public void downloadFileFromRemoteLocation(String serverlocation, File destinationFile) throws IOException
{
try (FileOutputStream fos = new FileOutputStream( destinationFile )){
URL url = new URL(serverlocation);
URLConnection connection = url.openConnection();
IOUtils.copy( connection.getInputStream(), fos);
}
}
if you want to stick to just Java then look at snippet below
try {
// Get the directory and iterate them to get file by file...
File file = new File(fileName);
if (!file.exists()) {
context.addMessage(new ErrorMessage("msg.file.notdownloaded"));
context.setForwardName("failure");
} else {
response.setContentType("APPLICATION/DOWNLOAD");
response.setHeader("Content-Disposition", "attachment"+
"filename=" + file.getName());
stream = new FileInputStream(file);
response.setContentLength(stream.available());
OutputStream os = response.getOutputStream();
os.close();
response.flushBuffer();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Categories