Trying to get image from Spring - java

My HTML file has the following command
<img src="/5/background" alt="" width="192" height="192">
Which I have bound to the following inside a #RestController in a Spring Boot application:
#RequestMapping(value = "/{connector}/background", method = RequestMethod.GET)
public File getConnectorBackgroundImage(#PathVariable("connector") int connector)
{
File image = new File("folder" + connector + "/myPicture");
return image;
}
I have done my debugging and I know the method is being entered, and I know the path is correct, but all that shows is the icon in the browser when there is a problem loading a picture.
What else am I missing?

Spring does not know how to handle the file that way. If you return a File, the controller will simply show you the path to the file if you call the REST API.
The proper way to do it is to read the file as a byte[]. Using commons-io you could come up with something like this:
File image = new File("folder" + connector + "/myPicture");
FileInputStream input = null;
try {
input = new FileInputStream(image);
return IOUtils.toByteArray(input);
} finally {
IOUtils.closeQuietly(input);
}
Another thing you shouldn't forget is to provide the mimetype. To do that you tweak the #RequestMapping annotation a bit by providing the produces property:
#RequestMapping(value = "/{connector}/background", method = RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)
This should do the trick.
EDIT: Didn't notice the comments, you already fixed it by yourself.

Related

How to return an Image to browser in rest API in JAVA from folder?

I have a folder in my NetBeans project with images. I have a H2 database with a "properties" table.
The images are named after a column in the properties table for convenience. This is my code so far.
#PostMapping(value = "/image/large/{id}", produces = MediaType.IMAGE_PNG_VALUE)
public ResponseEntity<Image> getPicture(#PathVariable long id)throws Exception{
System.out.println(id);
//System.out.println(barcode);
Properties prop1 = new Properties();
prop1 = propService.findOne(id);
String filepath = prop1.getPhoto();
String img = "static/images/"+filepath;
return img;
}
How can I implement this in my rest controller? Struggling to find a correct way to implement this, any help appreciated.
From the code you have provided, you can return a string representing an image location or path. This path can then be used in am image <img /> tag.
The second option is to read your file using an inputstream and convert the image to base46 (which you then return to the client).

How to test if I can upload a large multipart file

My code was initially breaking if I try and push a large file (anything above 1MB size). It is working fine now and able to accommodate the file sizes I want by adding the following in the properties file.
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
But how can I write a proper unit/integration test on this to ensure it allows file size up to 10MB?
The following has a good test example (the accepted answer) but it is using a mock file setup to test.
Using Spring MVC Test to unit test multipart POST request
Is there a way I could mock and specify file size?
Or actually pass in a real large file for testing (preferably not)?
Or a better way to do this, test I can accept a large file up to 10MB?
This is the method to be tested
#PostMapping(path = "/example", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<SomeResponse> upload(#PathVariable(#RequestPart("file") MultipartFile file) {
//we won't even get inside thi method and would fail if the file size is over 1MB previously.
// It works currently when I add files with size above 1MB
// cos I added the above 2 lines (spring.servlet.... in the properties file)
// some logic which works fine.
SomeResponse obj = //
return new ResponseEntity<>(obj, HttpStatus.OK);
}
This is current test (and there are other tests to test negative scenarios)
#Test
public void testValidUpload() throws Exception {
String fileContents = "12345";
String expectedFileContents = "12345\nSomeData";
mockServer.expect(requestTo("http://localhost:8080/example"))
.andExpect(method(HttpMethod.POST))
.andExpect(expectFile("file", "test.csv", expectedFileContents))
.andRespond(withStatus(HttpStatus.OK)
.contentType(MediaType.TEXT_PLAIN)
.body("done")
);
String response = this.mvc.perform(multipart("/example")
.file(new MockMultipartFile("file", "filename.csv", MediaType.TEXT_PLAIN_VALUE, fileContents.getBytes())))
.andExpect(status().isOk())
.andExpect(content().contentType(APPLICATION_JSON))
.andExpect(jsonPath("responseStatusCode", Matchers.equalTo("200")))
.andExpect(jsonPath("httpStatus", Matchers.equalTo("OK")))
.andReturn().getResponse().getContentAsString();
Response response = objectMapper.readValue(response, Response.class);
assertEquals(HttpStatus.OK, response.getHttpStatus());
assertEquals(5, response.id());
}
You can try something like this:
byte[] bytes = new byte[1024 * 1024 * 10];
MockMultipartFile firstFile = new MockMultipartFile("data", "file1.txt", "text/plain", bytes);
See documentation.
You can also refer to this article.

Downloaded file from server is different than original one saved previously

I cannot find out why the mp3 file is different after download from my server than original one saved previously there.
This is my controller method. The content of file (byte[] content) is identical with original file on this stage - the original file is the same as file retrieved from database (checked in debugger).
#ResponseBody
#RequestMapping(method = RequestMethod.GET, value = "/{sampleId}/file")
public HttpEntity<byte[]> getFile(#PathVariable Long sampleId) {
ResourceEntity resourceEntity = testSampleRepository.getFile(sampleId);
byte[] content = resourceEntity.getContent();
String fileName = resourceEntity.getFileName();
HttpHeaders header = new HttpHeaders();
header.setContentType(new MediaType("audio", "mpeg"));
header.set(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=" + fileName.replace(" ", "_"));
header.setContentLength(content.length);
return new HttpEntity<byte[]>(content, header);
}
This is how files differ (the left is original one):
Why passing using HTTP distors my file? Should mediaTypes enforce certain encoding? (there was no difference with "audio/mpeg" mediaType and without it).
It should work, if you set the produces = "application/octet-stream" attribute (MediaType.APPLICATION_OCTET_STREAM). Otherwise, you are trapped by Spring's converter framework.
You may want to have a look here, seems your problem is very similar: Spring MVC: How to return image in #ResponseBody? .

Java Spring Boot Restcontroller RequestMapping executed twice

I have a Spring Boot Application with a RestController and a method which will download and pass an image:
#RestController
public class PictureController {
#RequestMapping("/picture/{id}")
public HttpEntity<byte[]> getImage(#PathVariable String id) {
logger.info("Requested picture : >> " + id + " <<");
// !! Execute code for downloading !!
// Create Headers...
// return HttpEntity<byte[]>
}
}
In the logfiles I can read that the method is executed twice and I don't know why.
If I remove the code for downloading it gets executed just once as expected.
Is it because it takes a second to download it?
The code for downloading is...
byte[] response;
try {
URL url = new URL(....);
InputStream in = new BufferedInputStream(url.openStream());
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int n = 0;
while (-1 != (n = in.read(buf))) {
out.write(buf, 0, n);
}
out.close();
in.close();
response = out.toByteArray();
I also tried several solutions like...
#RequestMapping(value = "/picture2/{id}", headers = "Accept=image/jpeg, image/jpg, image/png, image/gif")
public #ResponseBody byte[] getArticleImage2(#PathVariable String id) {
I thought maybe a problem with HttpEntity but it's the same behaviour. Works as expected without code for downloading but with downloading an image it gets executed twice.
This is a serious performance issue of my application... :(
What is the problem here?
The problem depends on the Browser which is used to test the RestController.
I'am using Firefox... and Firefox tend to get some html around an image. But the method doesn't return html and so Firefox is starting another request... also for looking for a favicon.
Internet Explorer e.g. doesn't care about it and the method is only executed once as expected!
So my problem is not a real problem because later my image delivered by the RestController will be embedded in a website which has html and a favicon.

Spring mvc file upload

I'm working on spring mvc file upload. in the view, i use plupload multiple file upload plugin. here is my upload action:
#RequestMapping(value = CrudURI.uploadDo, method = RequestMethod.POST, produces = "application/json")
public #ResponseBody String uploadDo(#RequestBody MultipartFile file,
#RequestParam String name,
#RequestParam(required=false, defaultValue="-1") int chunks,
#RequestParam(required=false, defaultValue="-1") int chunk) {
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(new File("/uploads/"+name)));
stream.write(bytes);
stream.close();
} catch (Exception e) {
}
} else {
}
System.err.println(file.getOriginalFilename());
return null;
}
this action is working without any error or exception, but the uploaded file not saved. what's the problem?
thanks
Simply try following code:
File fileToSave=new File("/uploads/"+name);
file.transferTo(fileToSave);
And also make sure that you are actually getting file in mapping.
Darshan solution is correct, your original code has an issue that you're reading a file as getBytes() which is not using a buffer, but your writing using a buffer.
I think that your issue is most likely that you're trying to overwrite the uploaded file, at least it appears so based on your output location "/uploads/"+name. Try changing the name, and instead of having an empty catch block, add log for your exception it will point you to the issue

Categories