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

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.

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

Download rtf file spring boot

Good afternoon.
I need to download an rtf file that was put into the database as a byte[] to the user. The application runs on the server, and it coulnd be unloaded on the client's PC. I took methods from my previous project. There it was necessary to form and unload the exel file. I tried to upgrade them for this task, but I ran into one problem.
Naturally, I can't get the MediaType for byte[].
Tell me, can I somehow explicitly specify it?
public class MediaTypeUtils {
public static MediaType getMediaTypeForFileName(ServletContext servletContext, String fileName) {
String mineType = servletContext.getMimeType(fileName);
try {
MediaType mediaType = MediaType.parseMediaType(mineType);
return mediaType;
} catch (Exception e) {
return MediaType.APPLICATION_OCTET_STREAM;
}
} }
public static ResponseEntity<InputStreamResource> downloadFile1(ServletContext servletContext, PaymentOrderArchive archive) throws IOException {
MediaType mediaType = MediaTypeUtils.getMediaTypeForFileName(servletContext, archive.getRtffilename());
InputStream resource = null;
try (FileOutputStream stream = new FileOutputStream(archive.getRtffilename())) {
stream.write(archive.getEfile());
IOUtils.copyLarge(resource, stream);
InputStreamResource file = new InputStreamResource(resource);
return ResponseEntity.ok()
// Content-Disposition
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + archive.getRtffilename())
// Content-Type HERE
.contentType(mediaType)
// Contet-Length
.contentLength(resource.available()) //
.body(new InputStreamResource(resource));
}
}

Camel Routes - How to return the body response as xml

First of all, I am new with Spring Boot.
I am not sure if it is possible, but I would like to return the xml response from the external url.
I have this code:
#GetMapping("/myPage")
public void myPage() {
restConfiguration().host("localhost").port(8080);
from("timer://runOnce?repeatCount=1&delay=0")
.to("rest:get:/external-page")
.to("stream:out");
}
myPage() is returning a XML (that's OK). So, now I would like to return the same XML when I do:
curl http://localhost/myPage
I am not sure if I have to use .to("stream:out"), but the curl is returning an empty result.
Can someone help me?
Thanks in advance.
I found the solution, this is how to get the response.
CamelContext context = new DefaultCamelContext();
context.addRoutes(new RouteBuilder() {
public void configure() {
restConfiguration().host(sHost).port(iPort);
from("direct:start")
.setHeader(Exchange.HTTP_METHOD,simple("GET"))
.to("rest:get:/external-page");
}
});
context.start();
ProducerTemplate template = context.createProducerTemplate();
String headerValue = "application/xml";
Map<String, Object> headers = new HashMap<String,Object>();
headers.put("Content-Type", headerValue);
Object result = template.requestBodyAndHeaders("direct:start", null, headers, String.class);
Exchange exchange = new DefaultExchange(context);
String response = ExchangeHelper.convertToType(exchange, String.class, result);
context.stop();
return response;

spring : get response as Multipart File from REST WebService

I am creating POC for RESTFUL Web service using Spring 4.0. Requirement is to receive MultipartFile as Response from REST WEB-Service.
REST Service Controller
#RequestMapping(value="/getcontent/file", method=RequestMapping.post)
public MultipartFile getMultipartAsFileAsObject() {
File file = new File("src/test/resources/input.docx");
FileInputStream input = new FileInputStream(file);
MultipartFile multipartFile = new MockMultipartFile("file",file.getName(),
"application/docx", IOUtils.toByteArray(input));
return multipartFile
}
I call this service using third party Clients and Apache Http Client as well. kindly have a look on output.
Using Third party REST client ie. Postman
output looks like Json -
{
"name" : "file",
"originalfilename" : "sample.docx",
"contentType" : "application/docx",
"content" : [
82,
101,
97,
100,
101,
32,
32,
.
.
.
.
.
]
}
Apache HTTP Client Sample code
private static void executeClient() {
HttpClient client = new DefaultHttpClient();
HttpPost postReqeust = new HttpPost(SERVER_URI);
try{
// Set Various Attributes
HttpResponse response = client.execute(postReqeust) ;
//Verify response if any
if (response != null)
{
InputStream inputStream = response.getEntity().getContent();
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
OutputStream outputStream = new FileOutputStream
(new File("src/main/resource/sample.docx"));
outputStream.write(buffer);
outputStream.flush();
outputStream.close();
}
}
catch(Exception ex){
ex.printStackTrace();
}
Output of Apache Http client
file is getting Created but It is empty. (0 bytes).
I found some interesting answers from multiple stackoverflow questions.
Links are given below
file downloading in restful web services
what's the correct way to send a file from REST web service to client?
For Sending single file : (copied from above sources)
#GET
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getFile() {
File file = ... // Initialize this to the File path you want to serve.
return Response.ok(file, MediaType.APPLICATION_OCTET_STREAM)
.header("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"" ) //optional
.build();
}
For Sending Zip file : (copied from above sources)
1) Approach First :
You can use above method to send any file / Zip.
private static final String FILE_PATH = "d:\\Test2.zip";
#GET
#Path("/get")
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getFile() {
File file = new File(FILE_PATH);
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition", "attachment; filename=newfile.zip");
return response.build();
}
2) Approach Second :
#GET
#Path("/get")
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public StreamingOutput helloWorldZip() throws Exception {
return new StreamingOutput(){
#Override
public void write(OutputStream arg0) throws IOException, WebApplicationException {
// TODO Auto-generated method stub
BufferedOutputStream bus = new BufferedOutputStream(arg0);
try {
Thread.currentThread().getContextClassLoader().getResource("");
File file = new File("d:\\Test1.zip");
FileInputStream fizip = new FileInputStream(file);
byte[] buffer2 = IOUtils.toByteArray(fizip);
bus.write(buffer2);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}

Sending pdf/doc/txt/image files with JAXWS/cxf services Spring

Can someone provide me a demo of sending pdf files as response ?
Endpoint is
#GET
#Path("/PDFiles")
#WebMethod(operationName = "PDFiles")
public Response pdfiles() {
LOGGER.info("Getting FPodAUMFile.");
return dao.getPDFfiles(CacheKeys.pdffile);
}
DAO would be
public Response getPDFfiles(String pdffile) {
File file_pdf = new File("D:/pdffile.pdf");
// HELP ME SEND THIS PDFFILE.PDF AND COMPLETE THE CODE HERE
}
MTOM Simplifies the way it is sent. Can someone elaborate on using MTOM also ?
You need to specify Content-Disposition header in your response and write the file into the response entity. So for e.g.:
public Response getPDFfiles(String pdffile) {
File filePdf = new File("D:/pdffile.pdf"); //You'll need to convert your file to byte array.
ContentDisposition contentDisposition = new ContentDisposition("attachment;filename=pdffile.pdf");
return Response.ok(
new StreamingOutput() {
#Override
public void write(OutputStream outputStream) throws IOException, WebApplicationException {
outputStream.write(/* Your file contents as byte[] */);
}
})
.header("Content-Disposition", contentDisposition.toString())
.header("Content-Type", "application/pdf")
.build();
}
How to convert a file to byte[] can by found here.

Resources