how to access image folder in spring application - java

I like to access an image from the web/images directory. I like to access this image in the spring controller, so I can convert this image to byte[]. I am creating a chart and this image is part of the chart display. So, I am using this byte[] to construct Graphic2d object. Closest I have got to it is using this:
FileSystemResource resource = new FileSystemResource("images/"+imageName);
Currently, I have stored this image in the package structure. I like to do better than this. I like to read directly from web/images directory. Please give me some advice, Thanks.

The more elegant way is let your controller implement ServletContextAware so as your controller can injecte ServletContext instance, then you should use:
InputStream stream = servletContext.getResourceAsStream("/images/image.jpg");
int bytesRead;
byte[] buffer = new byte[8192];
while ((bytesRead = stream.read(buffer, 0, 8192)) != -1) {
//process image data, i.e. write to sompe place,etc.
}
//close the stream
stream.close();
BTW, as for servletContext.getRealPath, different servlet container might have different implementation, and it might not work after project packaged to a war file. so, it's recommended to use getResourceAsStream.

Well you can use servlet context to get the path to web/images. Use following code:
File file=new File(request.getSession().getServletContext().getRealPath("images/file.jpg"));
Note: Here I am utilizing request i.e. HttpServletRequest.

Related

How to convert MultipartFile properly to match for Microsoft AudioConfig?

In my Spring Boot application, I accept an audiofile as MultipartFile with #RequestParam. I know, I can convert the file into some InputStream. I am also able to convert it into some byte array:
#PostMapping("/microsoft")
void transcribe(#RequestParam("file") MultipartFile file) {
InputStream inputStream = new BufferedInputStream(file.getInputStream());
byte[] byteArr = file.getBytes();
AudioConfig audioConfig = AudioConfig.???; //here the correct method with my file needs to be called
}
For transcription using Microsoft API, I need to create some Audioconfig object. This is the link to the class.
I used in the past fromWavFileInput(...) when I loaded a local audio file. But now, I need to be able to use the MultipartFile. I have no idea which method of the AudioConfig class I can use and how to convert the file correctly.
The idea is, to create a temp file and transfer the MultipartFile into it:
File tempFile = File.createTempFile("prefix-", "-suffix");
file.transferTo(tempFile);
The use fromWavFileOutput with the path of the temporary file:
AudioConfig audioConfig = AudioConfig.fromWavFileOutput(tempFile.getPath());
For me, the temp file exceeds its maximum permitted size. To get this solved, make sure to add spring.servlet.multipart.max-file-size=-1 in your application.properties file to set limit to infinity.

Java: mock multipartfile in unit test

I am trying to mock a MultipartFile and I want to create the mock with a stream that I create in the test
I've tries with a file without much luck either. Here is what I have tried so far
FileInputStream stream = new
FileInputStream("MOCK_file.xlsm");
MultipartFile f1 = new MockMultipartFile("file1",stream);
MultipartFile[] files = {f1};
return files;
I get a fileNotFoundException. Where should I put my file in my Maven project so the unit tests can find the file?
-- OR --
How do I just create a stream in code without the use of a file?
Even better you can mock only the MultipartFile and you will not be needing the InputStream at all.
To do so you only need to do mock(MultiPartFile.class) and then define what each function will do
For example if you use the name
final MultipartFile mockFile = mock(MultipartFile.class);
when(mockFile.getOriginalFilename()).thenReturn("CoolName");
This way you wont have to bother with actual files neither unexpected responses as you will be defining them
How do I just create a stream in code without the use of a file?
You could use a ByteArrayInputStream to inject mock data. It's pretty straightforward for a small amount of data:
byte[] data = new byte[] {1, 2, 3, 4};
InputStream stream = new ByteArrayInputStream(data);
Otherwise, you need to figure out what directory is your code running from, which is something that depends on how it's being run. To help with that you could print the user.dir system property, which tells you the current directory:
System.out.println(System.getProperty("user.dir"));
Alternatively, you can use a full path, rather than a relative one to find the file.
Put the file in
src/test/resources/MOCK_file.xlsm
Read from JUnit class with:
InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("MOCK_file.xlsm");

Azure Storage Blob: Uploaded CSV file shows zero bytes

This problem I am facing in title is very similar to this question previously raised here (Azure storage: Uploaded files with size zero bytes), but it was for .NET and the context for my Java scenario is that I am uploading small-size CSV files on a daily basis (about less than 5 Kb per file). In addition the API code uses the latest version of Azure API that I am using in contrast against the 2010 used by the other question.
I couldn't figure out where have I missed out, but the other alternative is to do it in File Storage, but of course the blob approach was recommended by a few of my peers.
So far, I have mostly based my code on uploading a file as a block of blob on the sample that was shown in the Azure Samples git [page] (https://github.com/Azure-Samples/storage-blob-java-getting-started/blob/master/src/BlobBasics.java). I have already done the container setup and file renaming steps, which isn't a problem, but after uploading, the size of the file at the blob storage container on my Azure domain shows 0 bytes.
I've tried alternating in converting the file into FileInputStream and upload it as a stream but it still produces the same manner.
fileName=event.getFilename(); //fileName is e.g eod1234.csv
String tempdir = System.getProperty("java.io.tmpdir");
file= new File(tempdir+File.separator+fileName); //
try {
PipedOutputStream pos = new PipedOutputStream();
stream= new PipedInputStream(pos);
buffer = new byte[stream.available()];
stream.read(buffer);
FileInputStream fils = new FileInputStream(file);
int content = 0;
while((content = fils.read()) != -1){
System.out.println((char)content);
}
//Outputstream was written as a test previously but didn't work
OutputStream outStream = new FileOutputStream(file);
outStream.write(buffer);
outStream.close();
// container name is "testing1"
CloudBlockBlob blob = container.getBlockBlobReference(fileName);
if(fileName.length() > 0){
blob.upload(fils,file.length()); //this is testing with fileInputStream
blob.uploadFromFile(fileName); //preferred, just upload from file
}
}
There are no error messages shown, just we know that the file touches the blob storage and shows a size 0 bytes. It's a one-way process by only uploading CSV-format files. At the blob container, it should be showing those uploaded files a size of 1-5 KBs each.
Instead of blob.uploadFromFile(fileName); you should use blob.uploadFromFile(file.getAbsolutePath()); because uploadFromFile method requires absolute path. And you don't need the blob.upload(fils,file.length());.
Refer to Microsoft Docs: https://learn.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-java#upload-blobs-to-the-container
The Azure team replied to a same query I've put on mail and I have confirmed that the problem was not on the API, but due to the Upload component in Vaadin which has a different behavior than usual (https://vaadin.com/blog/uploads-and-downloads-inputs-and-outputs). Either the CloudBlockBlob or the BlobContainerUrl approach works.
The out-of-the-box Upload component requires manual implementation of the FileOutputStream to a temporary object unlike the usual servlet object that is seen everywhere. Since there was limited time, I used one of their addons, EasyUpload, because it had Viritin UploadFileHandler incorporated into it instead of figuring out how to stream the object from scratch. Had there been more time, I would definitely try out the MultiFileUpload addon, which has additional interesting stuff, in my sandbox workspace.
I had this same problem working with .png (copied from multipart files) files I was doing this:
File file = new File(multipartFile.getOriginalFilename());
and the blobs on Azure were 0bytes but when I changed to this:
File file = new File("C://uploads//"+multipartFile.getOriginalFilename());
it started saving the files properly

How do I load a FileResource into a byte array?

I have a file called data.dat that I would like to load into a byte[] in Vaadin. It is a data file that I need to load and then manipulate based on the user's input.
I tried:
String basepath = VaadinService.getCurrent().getBaseDirectory().getAbsolutePath();
FileResource resource = new FileResource(new File(basepath + MY_DATA_FILE));
The problem is that I don't know how to manipulate the resource to extract the byte[]. I see lots of information for how to put images and so on to the UI components, how to stream a user generated PDF, and so on, but I can't seem to find any examples on how to load your own data file that you then manipulate within code...
From the docs of vaadin you have:
java.io.File getSourceFile()
Gets the source file.
or
DownloadStream getStream()
Gets resource as stream.
And in DownloadStream:
java.io.InputStream getStream()
Gets downloadable stream.
So you can easily operate on File or InputStream to read the contents of a FileResource
For example in Java 8:
byte[] bytes = Files.readAllBytes(Paths.get(resource.getSourceFile().getAbsolutePath()));

Read file from classpath with Java 7 NIO

I've googled around for quite a while for this, but all the results point to pre-Java 7 NIO solutions. I've used the NIO stuff to read in files from the a specific place on the file system, and it was so much easier than before (Files.readAllBytes(path)). Now, I'm wanting to read in a file that is packaged in my WAR and on the classpath. We currently do that with code similar to the following:
Input inputStream = this.getClass().getClassLoader().getResourceAsStream(fileName);
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
/* iterate through the input stream to get all the bytes (no way to reliably find the size of the
* file behind the inputStream (see http://docs.oracle.com/javase/6/docs/api/java/io/InputStream.html#available()))
*/
int byteInt = -1;
try
{
byteInt = inputStream.read();
while (byteInt != -1)
{
byteStream.write(byteInt);
byteInt = inputStream.read();
}
byteArray = byteStream.toByteArray();
inputStream.close();
return byteArray;
}
catch (IOException e)
{
//...
}
While this works, I was hoping there was an easier/better way to do this with the NIO stuff in Java 7. I'm guessing I'll need to get a Path object that represents this path on the classpath, but I'm not sure how to do that.
I apologize if this is some super easy thing to do. I just cannot figure it out. Thanks for the help.
This works for me.
import java.nio.file.Files;
import java.nio.file.Paths;
// fileName: foo.txt which lives under src/main/resources
public String readFileFromClasspath(final String fileName) throws IOException, URISyntaxException {
return new String(Files.readAllBytes(
Paths.get(getClass().getClassLoader()
.getResource(fileName)
.toURI())));
}
A Path represents a file on the file system. It doesn't help to read a resource from the classpath. What you're looking after is a helper method that reads everything fro a stream (more efficiently than how you're doing) and writes it to a byte array. Apache commons-io or Guava can help you with that. For example with Guava:
byte[] array =
ByteStreams.toByteArray(this.getClass().getClassLoader().getResourceAsStream(resourceName));
If you don't want to add Guava or commons-io to your dependencies just for that, you can always read their source code and duplicate it to your own helper method.
As far as I understand, what you want is to open a ReadableByteChannel to your resource, so you can use NIO for reading it.
This should be a good start,
// Opens a resource from the current class' defining class loader
InputStream istream = getClass().getResourceAsStream("/filename.txt");
// Create a NIO ReadableByteChannel from the stream
ReadableByteChannel channel = java.nio.channels.Channels.newChannel(istream);
You should look at ClassLoader.getResource(). This returns a URL which represents the resource. If it's local to the file system, it will be a file:// URL. At that point you can strip off the scheme etc., and then you have the file name with which you can do whatever you want.
However, if it's not a file:// path, then you can fall back to the normal InputStream.

Categories

Resources