spring convert buffered image into response entity - spring

I have BufferedImage in my spring boot application. Now I want to send that file to user. How can I do that ?
I'm looking for method to convert BufferedImage into ResponseEntity.

you can also convert it to byte[] using javax.imageio.ImageIO
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(bufferedImage , "png", byteArrayOutputStream);
byte[] imageInByte = baos.toByteArray();
then you controller is simplified:
#RequestMapping(value = "/path", method = GET)
public ResponseEntity<byte[]> getResource() {
return ResponseEntity.status(HttpStatus.OK)
.header(HttpHeaders.CONTENT_DISPOSITION, "filename=\"image.png"\")
.contentType(MediaType.IMAGE_PNG)
.body(imageInByte);

Related

Spring MVC + Springfox 2.9.2 downloads damaged PDF

I have a Spring MVC project (no SpringBoot) with a GET endpoint which returns a PDF file. The PDF file is either generated manually or read from resources. I also have a SpringFox dependency to generate swagger-ui.html.
Dependency versions:
Spring: 4.3.25.RELEASE
SpringFox: 2.9.2
The problem is that when I try to download the PDF directly using the "Download file" button then the file is downloaded but somehow corrupted and impossible to open. But when I use the "Request URL" I'm able to download the PDF without any problem.
My REST request:
#RequestMapping(value = "/v1/generatePdfSync", method = RequestMethod.GET)
public ResponseEntity<Resource> generatePdfSync(#RequestParam String templateName) {
Map<String, Object> model = new HashMap<>();
model.put("title", "Hello world!");
model.put("pages", new ArrayList<>(Arrays.asList(1, 2, 3)));
byte[] bytes = pdfGenerator.generatePdf(templateName, model);
// Create response
ByteArrayResource resource = new ByteArrayResource(bytes);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.contentLength(resource.contentLength())
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"test.pdf\"")
.body(resource);
}
My question is whether I don't have some mistake in the request itself.
The error was mine, this code worked for me:
#RequestMapping(value = "/v2/generatePdfSync", method = RequestMethod.POST, produces = {MediaType.APPLICATION_PDF_VALUE, MediaType.APPLICATION_OCTET_STREAM_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE, MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<Resource> generatePdfSync(#RequestBody GeneratePdfRequest generatePdfRequest) {
// Map<String, Object> model = new HashMap<>();
// model.put("title", "Hello world!");
// model.put("pages", new ArrayList<>(Arrays.asList(1, 2, 3)));
LOGGER.info("GeneratePdfSync: {}", generatePdfRequest);
byte[] bytes = pdfGenerator.generatePdf(generatePdfRequest.getTemplateName(), generatePdfRequest.getTemplateModel());
// Create response
ByteArrayResource resource = new ByteArrayResource(bytes);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.contentLength(resource.contentLength())
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + generatePdfRequest.getResultPdfName() + "\"")
.body(resource);
}

Okhttp create MultipartBody with spring MultipartFile and json object

I have a controller like so that accepts a MultipartFile and json object:
#PostMapping(value = "/v1/submit")
public ResponseEntity submit(
#RequestParam(value="myFile", required = true) MultipartFile myFile
, #Valid #RequestPart(value="fileMeta", required=true) FileMeta fileMeta
){
I need to forward this to a new url using an okhttpclient post with a Multipartbody containing both myFile and fileMeta objects:
OkHttpClient client = new OkHttpClient();
MultipartBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("myFile", myFile.getName(), okhttp3.RequestBody.create(file, MediaType.parse("pdf"))
.addFormDataPart("fileMeta", fileMeta)
.build();
I am getting following error:
Cannot resolve method 'create(org.springframework.web.multipart.MultipartFile, okhttp3.MediaType)'
The method definition of OkHttp's RequestBody create is the following: create(MediaType contentType, byte[] content). It expects the first the MediaType and second the payload (either as byte[], File or other formats).
So you first have to switch the order of the method arguments and second convert the MultipartFile from Spring to a proper format that the create() method accepts, e.g. byte[] or File:
OkHttpClient client = new OkHttpClient();
MultipartBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("myFile", myFile.getName(), RequestBody.create(MediaType.parse("pdf"), file)
.addFormDataPart("fileMeta", fileMeta)
.build();
There are already multiple solutions available on StackOverflow to convert MultipartFile to File: How to convert a multipart file to File?
UPDATE: Example for using RestTemplate
#RestController
public class FileSendingController {
#PostMapping("/files")
public void streamFile(#RequestParam("file") MultipartFile file) {
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", file);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
RestTemplate restTemplate = new RestTemplate();
restTemplate.postForEntity("http://upload.to", requestEntity, String.class);
}
}

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.

SpringBoot base64 pdf downloading

When user makes a get request this should download a pdf file, so far I am getting base64 of the pdf file but I don't know how to download. Can someone help me out?
#ResponseBody
#GetMapping("/download/pdf/{uuid}/{userid}")
public String downloadPdf (#PathVariable String uuid,#PathVariable String userid, Model model) {
JSONObject jsonObject = RequestHelper.getResponse("pdf", uuid);
JSONArray d =(JSONArray) jsonObject.get("data");
String str = (String) d.get(0);
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
// I have base64 pdf how can I start downloading this pdf
return("file downloaded");
}
Add Rest Controller to spring boot project and below method to download pdf file from base64 content.
Assign the pdf base64 string to content variable.
#GetMapping(value = "/donw1")
public ResponseEntity<Resource> donw1() {
logger.info("Start the file processing");
String content = "<<Add_pdf_base64 content here>>";
byte[] decoder = Base64.getDecoder().decode(content);
InputStream is = new ByteArrayInputStream(decoder);
InputStreamResource resource = new InputStreamResource(is);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_PDF);
ContentDisposition disposition = ContentDisposition.attachment().filename("textdown.pdf").build();
headers.setContentDisposition(disposition);
return new ResponseEntity<>(resource, headers, HttpStatus.OK);
}

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);
}

Resources