loading dynamic image from local source - spring-boot

I have saved some images to local path of pc and saved the file name to db. Now i want to load all the image from db and show to html page using java script and thymemleaf. Browser says not allowed to load local resources , So i made a servlet in spring boot. But it does not showing image.
Servlet
#WebServlet("/admin/imgServlet")
public class AdminImageServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
String urlImage = request.getParameter("admin");
response.setContentType("image/jpeg");
ServletOutputStream out;
out = response.getOutputStream();
FileInputStream fin = new FileInputStream("C:/Users/Public/Documents/" + urlImage);
BufferedInputStream bin = new BufferedInputStream(fin);
BufferedOutputStream bout = new BufferedOutputStream(out);
int ch = 0;
while ((ch = bin.read()) != -1) {
bout.write(ch);
}
bin.close();
fin.close();
bout.close();
out.close();
}
}
#Bean
public ServletRegistrationBean adminImageServlet() {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(AdminImageServlet.class);
dispatcherServlet.setApplicationContext(applicationContext);
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(dispatcherServlet, "/admin/imgServlet");
servletRegistrationBean.setName("imgServlet");
return servletRegistrationBean;
}
Java script for loading image
'<img src=imgServlet?admin='+articles.bannerImg+' class="img-responsive" />'
error i'm getting imgServlet:1 GET http://localhost/techtalks/admin/imgServlet?admin=pyjc4x0B.jpeg 404 (Not Found)
And i also want to load image from local resources to thymeleaf html page
model.addAttribute("localImg", "E:\\picz\\assasins.jpg"); spring controller will pass the Model like this and it will pass the image to respective file to html page like this.
<img th:src="#{${localImg}}"/>

Your Servlet code works for me. I am able to get the image successfully.
I presume the problem could be most likely the file name. Please input the file name as below (i.e. without 'e' in jpeg).
It should work if the file is present in the local path that you are referring.
pyjc4x0B.jpg

Related

Testing file upload in Spring Boot leads to FileUploadException (multipart boundary was not set)

I'm trying to upload files to my Spring Boot application and directly writing them to their destination (not in a temp file first). The application code I have works, but I can't get my unit test to work. My controller looks like this:
#PostMapping("/upload")
#ResponseBody
public String handleFileUpload(final HttpServletRequest request) throws IOException {
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (!isMultipart) {
throw new ResponseStatusException(BAD_REQUEST, "Input was not of type multipart");
}
ServletFileUpload upload = new ServletFileUpload();
FileItemIterator fileIterator = upload.getItemIterator(request);
while (fileIterator.hasNext()) {
FileItemStream item = fileIterator.next();
if (!item.isFormField()) {
// Save the file
try {
return myFileStorageService.store(item.openStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
throw new ResponseStatusException(BAD_REQUEST, "Input did not contain a file");
}
This code works great, but my test doesn't:
#MockBean
private MyFileStorageService myFileStorageService;
#Autowired
private MockMvc mockMvc;
#Test
void shouldUploadFile() throws Exception {
final InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("testfile.txt");
final MockMultipartFile testFile = new MockMultipartFile("file", "testfile.txt", null, inputStream);
doReturn("success!").when(myFileStorageService).store(testFile);
mockMvc.perform(multipart("/upload").file(testFile))
.andExpect(status().isOk())
.andExpect(content().string("success!"));
verify(myFileStorageService).store(testFile);
}
This results in the following exception:
org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
at org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl.init(FileItemIteratorImpl.java:189)
at org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl.getMultiPartStream(FileItemIteratorImpl.java:205)
at org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl.findNextItem(FileItemIteratorImpl.java:224)
at org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl.<init>(FileItemIteratorImpl.java:142)
at org.apache.tomcat.util.http.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:252)
at org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload.getItemIterator(ServletFileUpload.java:134)
at com.lolmewn.FileUploadController.handleFileUpload(FileUploadController.java:128)
...
And in my config, I have configured the following:
spring:
servlet:
multipart:
enabled: false
max-file-size: -1
max-request-size: -1
I expect Spring would generate the multipart boundaries for me, just like the browser or Postman do, is this not the case? I saw many similar questions, with most of them explicitly setting their content-type as the primary error, but as far as I know I'm not setting a content-type anywhere, so I expect Spring to generate it for me.
If you are using default application.properties, then add #SpringBootTest annotation at top of your class which will instantiate it. If using something like application-test.properties you need to include #ActiveProfiles(test)
as well.
If you are using a config class to represent it
#EnableConfigurationProperties(value = YourConfig.class)
EDIT: Change
final MockMultipartFile testFile = new MockMultipartFile("file", "testfile.txt", null, inputStream);
To
final MockMultipartFile testFile = new MockMultipartFile("file", "testfile.txt",
MediaType.MULTIPART_FORM_DATA_VALUE, inputStream);

How to use MockMVC test the controller which use org.apache.commons.fileupload?

My Controller use " org.apache.commons.fileupload " realized the file UPload.
see it:
#PostMapping("/upload")
public String upload2(HttpServletRequest request) throws Exception {
ServletFileUpload upload = new ServletFileUpload();
FileItemIterator iter = upload.getItemIterator(request);
boolean uploaded = false;
while (iter.hasNext() && !uploaded) {
FileItemStream item = iter.next();
if (item.isFormField()) {
item.openStream().close();
} else {
String fieldName = item.getFieldName();
if (!"file".equals(fieldName)) {
item.openStream().close();
} else {
InputStream stream = item.openStream();
// dosomething here.
uploaded = true;
}
}
}
if (uploaded) {
return "ok";
} else {
throw new BaseResponseException(HttpStatus.BAD_REQUEST, "400", "no file field or data file is empty.");
}
}
and my MockMvc code is
public void upload() throws Exception {
File file = new File("/Users/jianxiaowen/Documents/a.txt");
MockMultipartFile multipartFile = new MockMultipartFile("file", new FileInputStream(file));
HashMap<String, String> contentTypeParams = new HashMap<String, String>();
contentTypeParams.put("boundary", "----WebKitFormBoundaryaDEFKSFMY18ehkjt");
MediaType mediaType = new MediaType("multipart", "form-data", contentTypeParams);
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post(baseUrl+"/upload")
.content(multipartFile.getBytes())
.contentType(mediaType)
.header(Origin,OriginValue)
.cookie(cookie))
.andReturn();
logResult(mvcResult);
}
my controller is right , it has successed in my web project,
but I want to test it use MvcMock, it has some mistake, see :
can someOne can help me?
"status":"400","msg":"no file field or data file is empty.","data":null
I don't know why it says my file is empty.
my English is poor, thank you very much if someone can help me.
The MockMvc can be used for integration testing for controllers using Apache Commons Fileupload too!
Import the org.apache.httpcomponents:httpmime into your pom.xml or gradle.properties
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.13</version>
</dependency>
Update the code to use MultipartEntityBuilder to build the multipart request on the client, and then serialize the entity into bytes, which is then set in the request content
public void upload() throws Exception {
File file = new File("/Users/jianxiaowen/Documents/a.txt");
String boundary = "----WebKitFormBoundaryaDEFKSFMY18ehkjt";
// create 'Content-Type' header for multipart along with boundary
HashMap<String, String> contentTypeParams = new HashMap<String, String>();
contentTypeParams.put("boundary", boundary); // set boundary in the header
MediaType mediaType = new MediaType("multipart", "form-data", contentTypeParams);
// create a multipart entity builder, and add parts (file/form data)
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
HttpEntity multipartEntity = MultipartEntityBuilder.create()
.addPart("file", new FileBody(file, ContentType.create("text/plain"), file.getName())) // add file
// .addTextBody("param1", "value1") // optionally add form data
.setBoundary(boundary) // set boundary to be used
.build();
multipartEntity.writeTo(outputStream); // or getContent() to get content stream
byte[] content = outputStream.toByteArray(); // serialize the content to bytes
MvcResult mvcResult = mockMvc.perform(
MockMvcRequestBuilders.post(baseUrl + "/upload")
.contentType(mediaType)
.content(content) // finally set the content
.header(Origin,OriginValue)
.cookie(cookie)
).andReturn();
logResult(mvcResult);
}
Can you try the below?
mockMvc.perform(
MockMvcRequestBuilders.multipart(baseUrl+"/upload")
.file(multiPartFile)
).andReturn();
Update:
You need to update the controller to handle the MultipartFile:
#PostMapping("/upload")
public String upload2(#RequestParam(name="nameOfRequestParamWhichContainsFileData")
MultipartFile uploadedFile, HttpServletRequest request) throws Exception {
//the uploaded file gets copied to uploadedFile object.
}
You need not use another library for managing file uploads. You can use the file upload capabilities provided by Spring MVC.

How to serve sitemap.xml from outside project folder in Spring Boot 2

I have a Spring Boot 2 Web application which is a blogging website, where I have a dynamic sitemap.xml file. The sitemap.xml gets updated whenever we add a new article in the repository. Now I need to serve the sitemap.xml file from outside of the project location. Consider the sitemap.xml is present in the following location:
/home/admin/sitemap.xml
My requirement is, whenever a user hit the url https://<my_url>/sitemap.xml then the file should be served from the mentioned location. I have added the mapping for the same.
#Configuration
#AutoConfigureAfter(DispatcherServletAutoConfiguration.class)
public class WebConfiguration implements WebMvcConfigurer {
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/sitemap.xml/**").addResourceLocations("/home/admin/sitemap.xml");
}
}
But the code is not working. Can anyone suggest that, what I am doing wrong here.
Finally, I have solved this by writing a GetMapping. Many solutions on the internet are saying that to return the sitemap.xml file as a String. But please note Google will not read that sitemap.xml file for the wrong Content-Type header. The Content-Type must be "application/xml". Following is my #GetMapping
#GetMapping(value = "/sitemap.xml")
public void serveSiteMapFile(HttpServletResponse response) throws IOException {
response.setContentType("application/xml");
try (BufferedReader bufferedReader =
new BufferedReader(new FileReader(new File("/home/admin/sitemap.xml")))) {
String line;
StringBuilder siteMapBuilder = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
siteMapBuilder.append(line);
}
ServletOutputStream outStream = response.getOutputStream();
outStream.println(siteMapBuilder.toString());
outStream.flush();
outStream.close();
}
}

How to return image in Spring REST to browser

I need to return image in my Spring controller.
I try answer in this Spring MVC: How to return image in #ResponseBody? but it's not working
my code is like this
#RequestMapping(value = "cabang/photo", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<byte[]> getPhoto() throws IOException {
File imgPath = new File("D:\\test.jpg");
byte[] image = Files.readAllBytes(imgPath.toPath());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_JPEG);
headers.setContentLength(image.length);
return new ResponseEntity<>(image, headers, HttpStatus.OK);
}
but when I access it in browser, it doesn't show anything (just no picture icon). But if I read the image byte array, it is not empty.
Do I miss anything in my code?
Your code looks ok. Make sure you added ByteArrayHttpMessageConverter to your application's list of http message converters.
Java Config :
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
ByteArrayHttpMessageConverter byteConverter = new ByteArrayHttpMessageConverter();
converters.add(byteConverter);
super.configureMessageConverters(converters);
}

Upload file from applet to Spring MVC

In my application I am running an applet to scan a picture from client. I need to upload the scanned file to the server then to database. I can upload the file by submitting a form in JSP, but I need the applet to post the file to URL.
Any hep would be appreciated.
Here is the code:
public static void main(String[] args) throws Exception {
URL url = new URL("http://localhost:8080/spring/upload");
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "text/html;charset=UTF-8");
connection.setRequestProperty("enctype", "multipart/form-data");
DataOutputStream printout = new DataOutputStream(
connection.getOutputStream());
printout.write(FileUtils.readFileToByteArray(new File("c:\\img_khar.jpg")));
printout.flush();
printout.close();
BufferedReader in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String decodedString;
while ((decodedString = in.readLine()) != null) {
System.out.println(decodedString);
}
in.close();
}
I prefer to use http client from apache for cases like this. They provide a MultipartEntity class that can be added to your HttpPost.
http://hc.apache.org/httpcomponents-client-ga/httpmime/apidocs/org/apache/http/entity/mime/MultipartEntity.html

Resources