FileNotFoundException when converting image to base64 kotlin - java

I have a few images in folders that I want to send back to the user. To do that, I convert the images to base64 and just display them in the front-end. This works for most of the images, but for some reason I get a FileNotFound exception with this one image below.
Code: get the jobs, which contains information and a company object in it. Converting the job images works fine, but when I add the conversion for the company logo it says FileNotFound.
#GetMapping
fun getAllJobs(): ResponseEntity<*> {
return try {
val jobList: List<Job> = jobRepository.findAll()
jobList.map {
val file = FileUtils.readFileToByteArray(File("images/job/"+it.jobImage))
val companyFile = FileUtils.readFileToByteArray(File("images/company/"+it.company.logo))
it.company.logo = "data:image/jpeg;base64,"+Base64.getEncoder().encodeToString(companyFile)
it.jobImage = "data:image/jpeg;base64,"+Base64.getEncoder().encodeToString(file)
}
JsonDataResponse(HttpStatus.OK, "Retrieved lists of jobs ", jobList).createResponseEntity()
} catch (e: Exception) {
JsonResponse(HttpStatus.INTERNAL_SERVER_ERROR, e.message.toString()).createResponseEntity()
}
}
The images folder:
When I debug and I see what the map is doing, this is the first state of the job object, the logo and jobimage are just references:
After the first iteration, the images are correctly converted in both objects:
After the second iteration, I'm getting this error:

Related

Parsing different file types

I am learning Kotlin and facing some difficulties understanding how I can proceed
Currently I have a kml file that gets sent from the front end but now I would like to accept geoJson and store this i database -> so I need to create a function in Kotlin to validate file type and based on type return the correct object.
This the function that accepts kml file and calls parseKmlToPolygons
fun parseKmlToPolygons(file: MultipartFile, applicationConfiguration: ApplicationConfiguration): Geometry {
if (file.size > applicationConfiguration.getMaxKmlUploadFileSizeLimitInBytes()) {
throw FileUploadSizeLimitReachedException()
}
return parseMultiParFileToPolygons(file.inputStream)
}
private fun parseKmlToPolygons(content: InputStream): Geometry {
try {
val kml = Kml.unmarshal(content) ?: throw InvalidKmlException("Failed to parse the kml file")
return toGeometry(kml.feature)
} catch (ex: IllegalArgumentException) {
throw InvalidKmlException(ex.localizedMessage, ex)
} catch (ex: InvalidGeometryException) {
throw InvalidKmlException(ex.localizedMessage, ex)
}
}
So I probably need to create a function that detects a correct file, but is it ok for me to return type Any here? Also, is it possible to get the type of the file from inputStream?
private fun detectFileType():Any {
}
My apologies if I am not really clear here, all I need is to replace the function that takes kml files to be able to take either kml or geoJson
Update
//todo would be better to have detection logic separate
private fun parseKmlToPolygons(file: MultipartFile): Geometry {
val fileExtension: String = FilenameUtils.getExtension(file.originalFilename)
if (fileExtension == PolygonFileType.KML.name) {
return parseKmlToPolygons(file.inputStream)
} else if (fileExtension == PolygonFileType.GEOJSON.name) {
return parseKmlToPolygons(file.inputStream)
}
throw FormatNotSupportedException("File format is not supported")
}
Actually, what do you mean by the "file type"? Both types, geoJson and kml, are text files. They do not have any magic-number encoded defining the type. So, I see the following options:
use extension of the original file uploaded by the user. For that you could use MultipartFile.getOriginalFilename
use content type set by the FE when uploading the file. MultipartFile.getContentType. Most likely it won't work out of the box and you will need to adjust your frontend.
check actual file content. It's the most comlex option, but as the kml is xml-based and the geoJson is JSON-based it should be feasable.
and finally the simplest solution: create separate endpoints for both types.

How to use Azure storage blob services [duplicate]

This question already has answers here:
Compiler error "archive for required library could not be read" - Spring Tool Suite
(24 answers)
Closed 4 years ago.
I need your help as I am new to this field. I want to use Azure storage blob service to upload images, list and download, but I am facing some problems.
I have imported a project from this repository, and as soon as I import I am getting errors:
Description Resource Path Location Type
Archive for required library: 'C:/Users/NUTRIP-DEVLP1/.m2/repository/org/apache/commons/commons-lang3/3.4/commons-lang3-3.4.jar' in project 'blobAzureApp' cannot be read or is not a valid ZIP file blobAzureApp Build path Build Path Problem
Description Resource Path Location Type
The project cannot be built until build path errors are resolved blobAzureApp Unknown Java Problem
Should I run this as a normal Java application or a Maven project? If Maven, how do I run it?
I suggest you using official java sdk in your maven project.
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-storage-blob</artifactId>
<version>10.1.0</version>
</dependency>
sample upload code:
static void uploadFile(BlockBlobURL blob, File sourceFile) throws IOException {
FileChannel fileChannel = FileChannel.open(sourceFile.toPath());
// Uploading a file to the blobURL using the high-level methods available in TransferManager class
// Alternatively call the Upload/StageBlock low-level methods from BlockBlobURL type
TransferManager.uploadFileToBlockBlob(fileChannel, blob, 8*1024*1024, null)
.subscribe(response-> {
System.out.println("Completed upload request.");
System.out.println(response.response().statusCode());
});
}
sample list code:
static void listBlobs(ContainerURL containerURL) {
// Each ContainerURL.listBlobsFlatSegment call return up to maxResults (maxResults=10 passed into ListBlobOptions below).
// To list all Blobs, we are creating a helper static method called listAllBlobs,
// and calling it after the initial listBlobsFlatSegment call
ListBlobsOptions options = new ListBlobsOptions(null, null, 10);
containerURL.listBlobsFlatSegment(null, options)
.flatMap(containersListBlobFlatSegmentResponse ->
listAllBlobs(containerURL, containersListBlobFlatSegmentResponse))
.subscribe(response-> {
System.out.println("Completed list blobs request.");
System.out.println(response.statusCode());
});
}
private static Single <ContainersListBlobFlatSegmentResponse> listAllBlobs(ContainerURL url, ContainersListBlobFlatSegmentResponse response) {
// Process the blobs returned in this result segment (if the segment is empty, blobs() will be null.
if (response.body().blobs() != null) {
for (Blob b : response.body().blobs().blob()) {
String output = "Blob name: " + b.name();
if (b.snapshot() != null) {
output += ", Snapshot: " + b.snapshot();
}
System.out.println(output);
}
}
else {
System.out.println("There are no more blobs to list off.");
}
// If there is not another segment, return this response as the final response.
if (response.body().nextMarker() == null) {
return Single.just(response);
} else {
/*
IMPORTANT: ListBlobsFlatSegment returns the start of the next segment; you MUST use this to get the next
segment (after processing the current result segment
*/
String nextMarker = response.body().nextMarker();
/*
The presence of the marker indicates that there are more blobs to list, so we make another call to
listBlobsFlatSegment and pass the result through this helper function.
*/
return url.listBlobsFlatSegment(nextMarker, new ListBlobsOptions(null, null,1))
.flatMap(containersListBlobFlatSegmentResponse ->
listAllBlobs(url, containersListBlobFlatSegmentResponse));
}
}
sample download code:
static void getBlob(BlockBlobURL blobURL, File sourceFile) {
try {
// Get the blob using the low-level download method in BlockBlobURL type
// com.microsoft.rest.v2.util.FlowableUtil is a static class that contains helpers to work with Flowable
blobURL.download(new BlobRange(0, Long.MAX_VALUE), null, false)
.flatMapCompletable(response -> {
AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths
.get(sourceFile.getPath()), StandardOpenOption.CREATE, StandardOpenOption.WRITE);
return FlowableUtil.writeFile(response.body(), channel);
}).doOnComplete(()-> System.out.println("The blob was downloaded to " + sourceFile.getAbsolutePath()))
// To call it synchronously add .blockingAwait()
.subscribe();
} catch (Exception ex){
System.out.println(ex.toString());
}
}
More details, please refer to this doc.Hope it helps you.

How to retrieve the file name of an image in Parse.com, for an Android app

I am storing small images inside a table. The field called "questionImage" is storing these images.
The table looks as follows:
I have two questions:
How can I retrieve the file name of the image files? For example, the first object in the table above has an image named "5D_C.png". How can I get that name using Java in Aandroid? I am using Eclipse, if that makes any difference.
Is there a way to import these images in a batch? For example, if I didn't have any image fields, I could have made an Excel sheet of my data and exported it as CSV into Parse.com. Is the same workflow achievable with image fields inside a class?
First you have to make a Parse query to obtain for the objects you are interested in. See here
Then, in the callback, you can iterate over these elements to collect the file names. Something like this:
public void done(List<ParseObject> objsList, ParseException e) {
if (e == null) {
Log.d("score", "Retrieved " + objsList.size() + " things");
ArrayList<String> fileNames = new ArrayList<>();
for (ParseObject ob : objsList) {
//This is the important part
String fileName = ob.getParseFile("questionImage").getName();
fileNames.add(fileName);
}
} else {
Log.d("score", "Error: " + e.getMessage());
}
}
Similarily, if you want to obtain the files, you can (in the same interation), get the file and save it
byte[] bitmapdata = ob.getParseFile("questionImage").getData();
Bitmap bm = BitmapFactory.decodeByteArray(bitmapdata, 0, bitmapdata.length);
//Save bitmap in a file
Hope this helps.
UPDATE: not sure if I understood correctly your question. With "import" you mean get the images from parse or upload them to parse. Parse is not designed to make massive operations (batch operations are quite limited).

Get GPS data from an image Java code

I would like to get the metadata from an image file in my local system using Java code
In the attached image you can see the desired data which i would like to pull from java code.
I wrote the below code and do not seem pull the data mentioned in the "Details" tab. The below code's output is and this is not what I look for.
Started ..
Format name: javax_imageio_jpeg_image_1.0
Format name: javax_imageio_1.0
Please give me your ideas. Thanks
try {
ImageInputStream inStream = ImageIO.createImageInputStream(new File("D:\\codeTest\\arun.jpg"));
Iterator<ImageReader> imgItr = ImageIO.getImageReaders(inStream);
while (imgItr.hasNext()) {
ImageReader reader = imgItr.next();
reader.setInput(inStream, true);
IIOMetadata metadata = reader.getImageMetadata(0);
String[] names = metadata.getMetadataFormatNames();
int length = names.length;
for (int i = 0; i < length; i++) {
System.out.println( "Format name: " + names[ i ] );
}
}
} catch (IOException e) {
e.printStackTrace();
}
There's no easy way to do it with the Java Core API. You'd have to parse the image's metadata tree, and interpret the proper EXIF tags. Instead, you can pick up the required code from an existing library with EXIF-parsing capabilities, and use it in yours. For example, I have used the Image class of javaxt, which provides a very useful method to extract GPS metadata from an image. It is as simple as:
javaxt.io.Image image = new javaxt.io.Image("D:\\codeTest\\arun.jpg");
double[] gps = image.getGPSCoordinate();
Plus, javaxt.io.Image has no external dependencies, so you can just use that particular class if you don't want to add a dependency on the entire library.
I suggest you read the EXIF header of the image and then parse the tags for finding the GPS information. In Java there is a great library (called metadata-extractor) for extracting and parsing the EXIF header. Please see the getting started for this library here.
Once you do the first 2 steps in the tutorial, look for the tags starting with [GPS] ([GPS] GPS Longitude, [GPS] GPS Latitude, ...).
Based on #dan-d answer, here is my code (kotlin)
private fun readGps(file: String): Optional<GeoLocation> {
// Read all metadata from the image
// Read all metadata from the image
val metadata: Metadata = ImageMetadataReader.readMetadata(File(file))
// See whether it has GPS data
val gpsDirectories = metadata.getDirectoriesOfType(
GpsDirectory::class.java)
for (gpsDirectory in gpsDirectories) {
// Try to read out the location, making sure it's non-zero
val geoLocation = gpsDirectory.geoLocation
if (geoLocation != null && !geoLocation.isZero) {
return Optional.of(geoLocation)
}
}
return Optional.empty()
}

Convert embedded pictures in database

I have a 'small' problem. In a database documents contain a richtextfield. The richtextfield contains a profile picture of a certain contact. The problem is that this content is not saved as mime and therefore I can not calculate the url of the image.
I'm using a pojo to retrieve data from the person profile and use this in my xpage control to display its contents. I need to build a convert agent which takes the content of the richtextitem and converts it to mime to be able to calculate the url something like
http://host/database.nsf/($users)/D40FE4181F2B86CCC12579AB0047BD22/Photo/M2?OpenElement
Could someone help me with converting the contents of the richtextitem to mime? When I check for embedded objects in the rt field there are none. When I get the content of the field as stream and save it to a new richtext field using the following code. But the new field is not created somehow.
System.out.println("check if document contains a field with name "+fieldName);
if(!doc.hasItem(fieldName)){
throw new PictureConvertException("Could not locate richtextitem with name"+fieldName);
}
RichTextItem pictureField = (RichTextItem) doc.getFirstItem(fieldName);
System.out.println("Its a richtextfield..");
System.out.println("Copy field to backup field");
if(doc.hasItem("old_"+fieldName)){
doc.removeItem("old_"+fieldName);
}
pictureField.copyItemToDocument(doc, "old_"+fieldName);
// Vector embeddedPictures = pictureField.getEmbeddedObjects();
// System.out.println(doc.hasEmbedded());
// System.out.println("Retrieved embedded objects");
// if(embeddedPictures.isEmpty()){
// throw new PictureConvertException("No embedded objects could be found.");
// }
//
// EmbeddedObject photo = (EmbeddedObject) embeddedPictures.get(0);
System.out.println("Create inputstream");
//s.setConvertMime(false);
InputStream iStream = pictureField.getInputStream();
System.out.println("Create notesstream");
Stream nStream = s.createStream();
nStream.setContents(iStream);
System.out.println("Create mime entity");
MIMEEntity mEntity = doc.createMIMEEntity("PictureTest");
MIMEHeader cdheader = mEntity.createHeader("Content-Disposition");
System.out.println("Set header withfilename picture.gif");
cdheader.setHeaderVal("attachment;filename=picture.gif");
System.out.println("Setcontent type header");
MIMEHeader cidheader = mEntity.createHeader("Content-ID");
cidheader.setHeaderVal("picture.gif");
System.out.println("Set content from stream");
mEntity.setContentFromBytes(nStream, "application/gif", mEntity.ENC_IDENTITY_BINARY);
System.out.println("Save document..");
doc.save();
//s.setConvertMime(true);
System.out.println("Done");
// Clean up if we are done..
//doc.removeItem(fieldName);
Its been a little while now and I didn't go down the route of converting existing data to mime. I could not get it to work and after some more research it seemed to be unnecessary. Because the issue is about displaying images bound to a richtextbox I did some research on how to compute the url for an image and I came up with the following lines of code:
function getImageURL(doc:NotesDocument, strRTItem,strFileType){
if(doc!=null && !"".equals(strRTItem)){
var rtItem = doc.getFirstItem(strRTItem);
if(rtItem!=null){
var personelDB = doc.getParentDatabase();
var dbURL = getDBUrl(personelDB);
var imageURL:java.lang.StringBuffer = new java.lang.StringBuffer(dbURL);
if("file".equals(strFileType)){
var embeddedObjects:java.util.Vector = rtItem.getEmbeddedObjects();
if(!embeddedObjects.isEmpty()){
var file:NotesEmbeddedObject = embeddedObjects.get(0);
imageURL.append("(lookupView)\\");
imageURL.append(doc.getUniversalID());
imageURL.append("\\$File\\");
imageURL.append(file.getName());
imageURL.append("?Open");
}
}else{
imageURL.append(doc.getUniversalID());
imageURL.append("/"+strRTItem+"/");
if(rtItem instanceof lotus.domino.local.RichTextItem){
imageURL.append("0.C4?OpenElement");
}else{
imageURL.append("M2?OpenElement");
}
}
return imageURL.toString()
}
}
}
It will check if a given RT field is present. If this is the case it assumes a few things:
If there are files in the rtfield the first file is the picture to display
else it will create a specified url if the item is of type Rt otherwhise it will assume it is a mime entity and will generate another url.
Not sure if this is an answer but I can't seem to add comments yet. Have you verified that there is something in your stream?
if (stream.getBytes() != 0) {
The issue cannot be resolved "ideally" in Java.
1) if you convert to MIME, you screw up the original Notes rich text. MIME allows only for sad approximation of original content; this might or might not matter.
If it matters, it's possible to convert a copy of the original field to MIME used only for display purposes, or scrape it out using DXL and storing separately - however this approach again means an issue of synchronization every time somebody changes the image in the original RT item.
2) computing URL as per OP code in the accepted self-answer is not possible in general as the constant 0.C4 in this example relates to the offset of the image in binary data of the RT item. Meaning any other design of rich text field, manually entered images, created by different version of Notes - all influence the offset.
3) the url can be computed correctly only by using C API that allows to investigate binary data in rich text item. This cannot be done from Java. IMO (without building JNI bridges etc)

Categories

Resources