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));
}
}
Related
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.
below is the android part
new MultipartUploadRequest(this,uploadid,UPLOAD_URL)
.addFileToUpload(path,"image")
.addParameter("name",name)
.setNotificationConfig(new UploadNotificationConfig())
.setMaxRetries(2)
.startUpload();
below is my java controller in web services
#RequestMapping(value = "/uploadm",method=RequestMethod.POST)
public void submitQuestionuploading(#RequestBody String image) throws Exception
{
System.out.println(1+""+image);
try {
byte[] bytes = image.getBytes();
System.out.println(11);
BufferedOutputStream stream =new BufferedOutputStream(new
FileOutputStream(new File(UPLOAD_DIRECTORY +"11.png")));
stream.write(bytes);
stream.flush();
stream.close();
}
catch (Exception e) {
System.out.println(e);
}
output is this one i got in console but file is created but it is corrupted and it s size 0bytes ,
---------AndroidUploadService1518510071115 Content-Disposition: form-data; name="image"; filename="IMG_20180211_000033.jpg"
Content-Type: image/jpeg
ÿØÿá3ØExif
i tried to put this in java controller but it is not working
#RequestMapping(value = "/upload", method = RequestMethod.POST ,
headers = "Content-Type=multipart/form-data") public String
fileUpload(#RequestParam("image") CommonsMultipartFile file) {}
but i want to do in spring MVC only, help me to take uploaded file
This is a working file uploader
#ResponseStatus(code = HttpStatus.CREATED)
#RequestMapping(value = "asset", method = RequestMethod.POST, consumes = {
MediaType.MULTIPART_FORM_DATA_VALUE}, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
#ResponseBody
public String uploadImage(
#RequestParam("image") MultipartFile file) {
byte[] bytes = file.getBytes();
//do something with byte
return "ok or anything you want to return";
}
And also you need to register MultipartResolver as a depandency.
#Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(100000);
return multipartResolver;
}
you can deploy this code and then test using postman.
there are various tutorials for this.
you may have a look at
http://www.baeldung.com/spring-file-upload
https://www.boraji.com/spring-4-mvc-file-upload-example-with-commons-fileupload
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();
}
}
};
}
Intro
I have spring MVC application I'm loading image from controller. For security purpose, I added X-Content-Type-Options:nosniff to my Spring application
By setting the following in springConfig xml <security:content-type-options/>
Problem : after this IE is not loading the images responded by controller. I suspect the content type is not set in the response. Because another site which is responding X-Content-Type-Options:nosniff and Content-Type:image/png; is working fine.
TRY1
I tried to change my controller to set content type. But it is not happening.
#RequestMapping(value = "/getUserImage" , produces = org.springframework.http.MediaType.IMAGE_PNG_VALUE)
public #ResponseBody
void getUserImage(
#RequestParam(value = "userId", required = false) int userId,
HttpServletRequest request, HttpServletResponse response) {
try {
//Get file and add it to response
IOUtils.copy(inputStream, response.getOutputStream());
response.getOutputStream().flush();
response.setContentType(org.springframework.http.MediaType.IMAGE_PNG_VALUE);
response.setHeader("Content-Type","image/png");
response.flushBuffer();
inputStream.close();
} catch (Exception e){
}
}
TRY2
I tried to add response header as the same way in method interceptor but still no luck.
But the same thing working in Chrome and Firefox.
Try this :
#RequestMapping(value = "/image/{personId}")
#ResponseBody
public HttpEntity<byte[]> getPhoto(#PathVariable int personId) {
Person person = this.personService.getPersonById(personId);
if (person != null && person.getProfileThumbnail() != null) {
try {
byte[] image;
try {
image = org.apache.commons.io.FileUtils.readFileToByteArray(new File(msg + "/" + person.getUsername() + "/" + personId + ".png"));
} catch (FileNotFoundException e) {
image = org.apache.commons.io.FileUtils.readFileToByteArray(new File(defaultProfilePath));
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
headers.setContentLength(image.length);
return new HttpEntity<>(image, headers);
} catch (IOException ignored) {
}
}
}
What I am basically doing is checking if there is an image on File-system for the user, if not then I am loading a default image. Right now it works on all browser, so even if personid is 0, I get default image back, with the else cause, which I have not posted here.
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.