Can't communicate MultiPart/data in Test (Jersey/Junit) - java

So i've had some trouble with doing Unit test of a method that parse PDFs
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.APPLICATION_JSON)
public Response parsingPdfOrange(#FormDataParam("fichier") InputStream uploadedInputStream,
#FormDataParam("fichier") FormDataContentDisposition fileDetail) {
try {
String uploadedFileLocation = "D:/tmp/doc.pdf";
String info = "facture Orange:"
+ OrangeService.ParseFacture(uploadedFileLocation, uploadedInputStream).toString();
return Response.status(201).entity(info).build();
which works fine my url give my the good result etc but
#Override
protected Application configure() {
return new ResourceConfig(OrangeWebService.class).register(MultiPartFeature.class);
}
#Override
protected void configureClient(ClientConfig config) {
config.register(MultiPartFeature.class);
}
#Test
public void parsePDF_NullPointerExcpetion() throws Exception {
try {
FileDataBodyPart filePart = new FileDataBodyPart("file", new File(pathtoRessources));
FormDataMultiPart formDataMultipart = new FormDataMultiPart();
FormDataMultiPart multipart = (FormDataMultiPart) formDataMultipart.bodyPart(filePart);
Response response = (target("pdf").request().post(Entity.entity(multipart, multipart.getMediaType())));
System.out.println(response);
response.close();
} catch (Exception e) {
e.printStackTrace();
}
this is my test code and the pb is here: it seems my FormDataMultiPart is fine but when i do Entity.entity(multipart, multipart.getMediaType() it gives back a null value because i get a nullPointerException on it.
I need help, Thanks a lot.

The file part name is "fichier"
#FormDataParam("fichier") InputStream uploadedInputStream
But you are sending it as "file"
FileDataBodyPart filePart = new FileDataBodyPart("file", new File(pathtoRessources));
Fix that.

Related

Error while sending Video File from Java Spring Microservice to other Microservice on other port using Spring Rest Template

Right now I have 2 Spring App.
App A will have a controller that will receive a video file ad Multipart file and sending the file to App B via rest template.
Some Code from App A that handle sending request to App B.
#RestController
public class AppAController {
#Autowired
private final AppBService service;
#PostMapping("/sendToB")
public ResponseEntity<String> contoller(#RequestParam("file") MultipartFile file) {
String result = service.sendToB(file);
return new ResponseEntity<>(result, HttpStatus.OK);
}
}
#Service
public class AppBService {
public String sendToB(MultipartFile file) throws ResponseStatusException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", file);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
String serverUrl = "http://127.0.0.1:8090/makeFrames";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(
serverUrl,
HttpMethod.POST,
requestEntity,
String.class
);
if (response.getStatusCode() != HttpStatus.OK) {
throw new ResponseStatusException(response.getStatusCode(), response.getBody());
}
return response.getBody();
}
}
And for App B, it will receive a video and extracting key frames from a video using JavaCV.
#RestController
public class ProcessorController {
#PostMapping("/makeFrames")
public ResponseEntity<String> framesExtractorController(#RequestParam("file") MultipartFile file) {
try {
File result = FramesExtractor.grabFrames(file);
return new ResponseEntity<>(result.getAbsolutePath(), HttpStatus.OK);
} catch (IOException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND);
}
}
}
public class FramesExtractor {
private static final Logger LOG = LoggerFactory.getLogger(FramesExtractor.class);
private FramesExtractor() {
}
public static File grabFrames(MultipartFile video) throws IOException {
LOG.info("Extracting Frames from the video " + video.getName());
String directoryName = video.getOriginalFilename() + "-frames-result";
directoryAssurance(directoryName);
try (FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(video.getInputStream());
Java2DFrameConverter converter = new Java2DFrameConverter()) {
frameGrabber.setImageWidth(480);
frameGrabber.setImageHeight(360);
frameGrabber.start();
Frame frame;
int i = 0;
while ((frame = frameGrabber.grabKeyFrame()) != null) {
BufferedImage bi = converter.getBufferedImage(frame);
ImageIO.write(bi, "png", new File(directoryName + "/" + String.format("%03d", i) + ".png"));
i++;
}
frameGrabber.stop();
LOG.info("Finish Extracting Frames");
return new File(directoryName);
} catch (Exception e) {
LOG.error(e.getMessage());
throw e;
}
}
}
Both app A and B have these properties set to their application.properties files.
server.port={There respective port}
spring.servlet.multipart.enabled=true
spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=100MB
And when i testing the application by using PostMan to send post request with video file in form-data body to App A /sendToB api i receive this error message.
"Type definition error: [simple type, class java.io.FileDescriptor]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.FileDescriptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile[\"inputStream\"]->java.io.FileInputStream[\"fd\"])"
So I want to ask what cause this problems and how I can fix it or sending video file to other Spring App running on other port properly.
I edited my previous answer because you can actually get parameters from a response body in a POST with #RequestParam annotation.
I would use JSON as content type. This is my solution:
public String sendToB(MultipartFile file) throws ResponseStatusException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
byte[] bytesFile = file.getBytes();
String base64String = Base64.getEncoder().encodeToString(bytesFile);
Map<String, Object> body = new HashMap<>();
body.put("file", base64String);
body.put("directoryName", file.getOriginalFilename());
body.put("videoName", file.getName())
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(body, headers);
String serverUrl = "http://127.0.0.1:8090/makeFrames";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(
serverUrl,
HttpMethod.POST,
requestEntity,
String.class
);
if (response.getStatusCode() != HttpStatus.OK) {
throw new ResponseStatusException(response.getStatusCode(), response.getBody());
}
return response.getBody();
}
For App B, the code would be:
#PostMapping("/makeFrames")
public ResponseEntity<String> framesExtractorController(#RequestBody Map<String, Object> requestBody) {
try {
String base64String = requestBody.get("file").toString();
byte[] bytesFile = Base64.getDecoder().decode(base64String);
InputStream inputStream = new ByteArrayInputStream(bytesFile);
String directoryName = requestBody.get("directoryName").toString();
String videoName = requestBody.get("videoName").toString();
File result = FramesExtractor.grabFrames(inputStream, directoryName, videoName);
return new ResponseEntity<>(result.getAbsolutePath(), HttpStatus.OK);
} catch (IOException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND);
}
}
}
public static File grabFrames(InputStream inputStream, String directoryName, String videoName) throws IOException {
//Your code
}

How to write java web services to upload image from android and use it in android

I see almost all webservice for android are written in PHP code. With Java I found an example of a rest service to upload image. I coded follow that code but when run test on my android device and Advanced RESTClient of chorme, I get error: HTTP Status 500 - Internal Server Error: Servlet.init () for servlet [Jersey REST Service] threw exception.. My URL: "http://srv.triaxvn.com:8080/logisticwsm/file/image-upload"
In android I use code:
#Override
protected String doInBackground(Void... params) {
return uploadFile();
}
#SuppressWarnings("deprecation")
private String uploadFile() {
File sourceFile = new File(filePath);
String fileName = sourceFile.getName();
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(FILE_UPLOAD_URL);
MultipartEntity entity = new MultipartEntity();
// Extra parameters if you want to pass to server
entity.addPart("fileDescription", new StringBody(""));
entity.addPart("fileName", new StringBody(fileName != null ? fileName : sourceFile.getName()));
// Adding file data to http body
FileBody fileBody = new FileBody(sourceFile, "application/octect-stream") ;
entity.addPart("attachment", fileBody);
//totalSize = entity.getContentLength();
httppost.setEntity(entity);
// Making server call
HttpResponse response = httpclient.execute(httppost);
HttpEntity r_entity = response.getEntity();
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
// Server response
responseString = EntityUtils.toString(r_entity);
} else {
responseString = "Error occurred! Http Status Code: "
+ statusCode;
}
My Restful web service code:
#Path("/file")
public class UploadFile {
private final String UPLOADED_FILE_PATH = "c:\\uploaded";
#POST
#Path("/image-upload")
#Consumes("multipart/form-data")
public Response uploadFile(MultipartFormDataInput input) throws IOException
{
//Get API input data
Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
//Get file name
String fileName = uploadForm.get("fileName").get(0).getBodyAsString();
//Get file data to save
List<InputPart> inputParts = uploadForm.get("attachment");
for (InputPart inputPart : inputParts)
{
try
{
//Use this header for extra processing if required
#SuppressWarnings("unused")
MultivaluedMap<String, String> header = inputPart.getHeaders();
// convert the uploaded file to inputstream
InputStream inputStream = inputPart.getBody(InputStream.class, null);
byte[] bytes = IOUtils.toByteArray(inputStream);
// constructs upload file path
fileName = UPLOADED_FILE_PATH + fileName;
writeFile(bytes, fileName);
System.out.println("Success !!!!!");
}
catch (Exception e)
{
e.printStackTrace();
return Response.status(200).entity("Uploaded file name : "+e.getMessage()).build();
}
}
return Response.status(200)
.entity("Uploaded file name : "+ fileName).build();
}
//Utility method
private void writeFile(byte[] content, String filename) throws IOException
{
File file = new File(filename);
if (!file.exists()) {
file.createNewFile();
}
FileOutputStream fop = new FileOutputStream(file);
fop.write(content);
fop.flush();
fop.close();
}
I do not know the error caused from by android code or Server Restful code and how to fix it

send a file from the server side to the client side using rest service

I want to send a file from the server side to the client side using rest service
I'm using spring MVC. I used this service method:
public ResponseEntity<InputStreamResource> postFile() throws Exception {
DocumentDaoImpl dao = new DocumentDaoImpl();
Document docCmis = (Document) dao.getDocument("workspace://SpacesStore/ae6d1722-0f08-49ab-a73b-c07036001318");
byte[] myByteArray = readContent(docCmis.getContentStream().getStream());
ClassPathResource myFile = new ClassPathResource(docCmis.getContentStreamFileName());
//System.out.println("eeeee"+pdfFile);
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
return ResponseEntity
.ok()
.headers(headers)
.contentLength(myByteArray.length)
.contentType(MediaType.parseMediaType("application/octet-stream"))
.body(new InputStreamResource(docCmis.getContentStream().getStream()));
}
and this function in a rest controller class
#RequestMapping(value = "/downloadPDFFile",produces = { "application/json" }, method = RequestMethod.GET)
#ResponseBody
public ResponseEntity downloadPDFFile() throws Exception {
return courriersArrivésServices.postFile();
}
then with a rest call using RestTemplate class,i tryied to get my file
Map<String, Object> selectedCourrier=restTemplate.getForObject(SERVER_URI + "/getCourrierDetails"+"?id="+id, HashMap.class);
But that didn't work for me and gives me this error
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class org.springframework.http.ResponseEntity] and content type [application/octet-stream]
Server side:
#RequestMapping("/download")
public byte[] download() throws Exception {
File f = new File("C:\\WorkSpace\\Text\\myDoc.txt");
byte[] byteArray = new byte[(int) f.length()];
byteArray = FileUtils.readFileToByteArray(f);
return byteArray;
}
Client side:
private ResponseEntity<byte[]> getDownload(){
URI end = URI.create("http://vmvdi05059:8080/ePaymentsWeb/download");
return rest.getForEntity(end,byte[].class);
}
public static void main(String[] args) throws Exception {
byte[] byteArray = new TestClient().getDownload().getBody();
FileOutputStream fos = new
FileOutputStream("C:\\WorkSpace\\testClient\\abc.txt");
fos.write(byteArray);
fos.close();
System.out.println("file written successfully..");
}

How to get multipartentity from httpservletrequest

I am trying to invoke a webservice from java spring controller. Below is the code
private void storeImages(MultipartHttpServletRequest multipartRequest) {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost(
"http://localhost:8080/dream/storeimages.htm");
MultipartFile multipartFile1 = multipartRequest.getFile("file1");
MultipartEntity multipartEntity = new MultipartEntity(
HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.addPart("file1",
new ByteArrayBody(multipartFile1.getBytes(),
multipartFile1.getContentType(),
multipartFile1.getOriginalFilename()));
postRequest.setEntity(multipartEntity);
HttpResponse response = httpClient.execute(postRequest);
if (response.getStatusLine().getStatusCode() != 201) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatusLine().getStatusCode());
}
}
Above is just partial code. I am trying to determine how to retrieve this on the server side. On the server side i have the following Spring controller code
#RequestMapping(value = "/storeimages.htm", method = RequestMethod.POST)
public ModelAndView postItem(HttpServletRequest request,
HttpServletResponse response) {
logger.info("Inside /secure/additem/postitem.htm");
try {
// How to get the MultipartEntity object here. More specifically i
// want to get back the Byte array from it
} catch (Exception ex) {
ex.printStackTrace();
}
return new ModelAndView("success");
}
I executed this code and my control is going to the server side. But i am stuck on how to get back the byte array from the multipartentity object.
Edited requirement:
Here is the requirement. User uploads the images from website (This is done and working) The control goes to the Spring controller after form submit (This is done and working) In Spring controller I am using Multipart to get the content of the form. (This is done and working) Now i want to call a webservices which will send the image byte array to image server.(This needs to be done) On the image server, i want to receive this webservice request get all the fields from HTTPServlerRequest, store the images and return(This needs to be done)
Finally resolved it. Here is what worked for me.
Client side
private void storeImages(HashMap<String, MultipartFile> imageList) {
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost("http://localhost:8080/dream/storeimages.htm");
MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
Set set = imageList.entrySet();
Iterator i = set.iterator();
while(i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
String fileName = (String)me.getKey();
MultipartFile multipartFile = (MultipartFile)me.getValue();
multipartEntity.addPart(fileName, new ByteArrayBody(multipartFile.getBytes(),
multipartFile.getContentType(), multipartFile.getOriginalFilename()));
}
postRequest.setEntity(multipartEntity);
HttpResponse response = httpClient.execute(postRequest);
if (response.getStatusLine().getStatusCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatusLine().getStatusCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));
String output;
while ((output = br.readLine()) != null) {
logger.info("Webservices output - " + output);
}
httpClient.getConnectionManager().shutdown();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Server side
#RequestMapping(value = "/storeimages.htm", method = RequestMethod.POST)
public void storeimages(HttpServletRequest request, HttpServletResponse response)
{
logger.info("Inside /secure/additem/postitem.htm");
try
{
//List<Part> formData = new ArrayList(request.getParts());
//Part part = formData.get(0);
//Part part = request.getPart("file1");
//String parameterName = part.getName();
//logger.info("STORC IMAGES - " + parameterName);
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Set set = multipartRequest.getFileMap().entrySet();
Iterator i = set.iterator();
while(i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
String fileName = (String)me.getKey();
MultipartFile multipartFile = (MultipartFile)me.getValue();
logger.info("Original fileName - " + multipartFile.getOriginalFilename());
logger.info("fileName - " + fileName);
writeToDisk(fileName, multipartFile);
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
public void writeToDisk(String filename, MultipartFile multipartFile)
{
try
{
String fullFileName = Configuration.getProperty("ImageDirectory") + filename;
FileOutputStream fos = new FileOutputStream(fullFileName);
fos.write(multipartFile.getBytes());
fos.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
In my project, we used to use MultipartParser from com.oreilly.servlets to handle HttpServletRequests corresponding to multipart requests, as follows:
// Should be able to handle multipart requests upto 1GB size.
MultipartParser parser = new MultipartParser(aReq, 1024 * 1024 * 1024);
// If the content type is not multipart/form-data, this will be null.
if (parser != null) {
Part part;
while ((part = parser.readNextPart()) != null) {
if (part instanceof FilePart) {
// This is an attachment or an uploaded file.
}
else if (part instanceof ParamPart) {
// This is request parameter from the query string
}
}
}
Hope this helps.
Instead of doing all that by hand, you can use Springs Mutlipart support
The controller can work like this (This example use a command object to store additional user inputs -- (this is an example from an working project)).
#RequestMapping(method = RequestMethod.POST)
public ModelAndView create(#Valid final DocumentCreateCommand documentCreateCommand,
final BindingResult bindingResult) throws IOException {
if (bindingResult.hasErrors()) {
return new ModelAndView("documents/create", "documentCreateCommand", documentCreateCommand);
} else {
Document document = this.documentService.storeDocument(
documentCreateCommand.getContent().getBytes(),
StringUtils.getFilename(StringUtils.cleanPath(documentCreateCommand.getContent().getOriginalFilename())));
//org.springframework.util.StringUtils
return redirectToShow(document);
}
}
#ScriptAssert(script = "_this.content.size>0", lang = "javascript", message = "{validation.Document.message.notDefined}")
public class DocumentCreateCommand {
#NotNull private org.springframework.web.multipart.MultipartFile content;
Getter/Setter
}
To enable Spring Multipart support you need to configure some stuff:
web.xml (Add org.springframework.web.multipart.support.MultipartFilter after CharacterEncodingFilter and before HttpMethodFilter)
<filter>
<filter-name>MultipartFilter</filter-name>
<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
<!-- uses the bean: filterMultipartResolver -->
</filter>
<filter-mapping>
<filter-name>MultipartFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
In your Spring Configuration for the CORE (not MVC Servlet) of your application add this
<!-- allows for integration of file upload functionality, used by an filter configured in the web.xml -->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="filterMultipartResolver" name="filterMultipartResolver">
<property name="maxUploadSize" value="100000000"/>
</bean>
Then you also need the commons fileupload libary, because the Spring MultipartFile is just some kind of Addapter
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.1</version>
</dependency>
For some more Details:
#See Spring Reference, Chapter 15.8 Spring's multipart (fileupload) support
to deal with spring files to the controller. you need to indicate, in your app-config.xml as follows:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
and treat code as follows
MultipartEntityBuilder paramsBuilder = MultipartEntityBuilder.create();
Charset chars = Charset.forName("UTF-8");
paramsBuilder.setCharset(chars);
if (null != obj.getFile()){
FileBody fb = new FileBody(obj.getFile());
paramsBuilder.addPart("file", fb);
}
and this for red multipart
private File getFile(MultipartFile file) {
try {
File fichero = new File(file.getOriginalFilename());
fichero.createNewFile();
FileOutputStream fos = new FileOutputStream(fichero);
fos.write(file.getBytes());
fos.close();
return fichero;
} catch (Exception e) {
return null;
}
}
I hope this helps.

Return File From Resteasy Server

Hi, I wanted to return a file from a resteasy server. For this purpose, I have a link at the client side which is calling a rest service with ajax. I want to return the file in the rest service. I tried these two blocks of code, but both didn't work as I wanted them to.
#POST
#Path("/exportContacts")
public Response exportContacts(#Context HttpServletRequest request, #QueryParam("alt") String alt) throws IOException {
String sb = "Sedat BaSAR";
byte[] outputByte = sb.getBytes();
return Response
.ok(outputByte, MediaType.APPLICATION_OCTET_STREAM)
.header("content-disposition","attachment; filename = temp.csv")
.build();
}
.
#POST
#Path("/exportContacts")
public Response exportContacts(#Context HttpServletRequest request, #Context HttpServletResponse response, #QueryParam("alt") String alt) throws IOException {
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=temp.csv");
ServletOutputStream out = response.getOutputStream();
try {
StringBuilder sb = new StringBuilder("Sedat BaSAR");
InputStream in =
new ByteArrayInputStream(sb.toString().getBytes("UTF-8"));
byte[] outputByte = sb.getBytes();
//copy binary contect to output stream
while (in.read(outputByte, 0, 4096) != -1) {
out.write(outputByte, 0, 4096);
}
in.close();
out.flush();
out.close();
} catch (Exception e) {
}
return null;
}
When I checked from the firebug console, both of these blocks of code wrote "Sedat BaSAR" in response to the ajax call. However, I want to return "Sedat BaSAR" as a file. How can I do that?
Thanks in advance.
There're two ways to to it.
1st - return a StreamingOutput instace.
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response download() {
InputStream is = getYourInputStream();
StreamingOutput stream = new StreamingOutput() {
public void write(OutputStream output) throws IOException, WebApplicationException {
try {
output.write(IOUtils.toByteArray(is));
}
catch (Exception e) {
throw new WebApplicationException(e);
}
}
};
return Response.ok(stream, MediaType.APPLICATION_OCTET_STREAM).header("content-disposition", "attachment; filename=\"temp.csv\"").build();
}
You can return the filesize adding Content-Length header, as the following example:
return Response.ok(stream, MediaType.APPLICATION_OCTET_STREAM).header("content-disposition", "attachment; filename=\"temp.csv\"").header("Content-Length", getFileSize()).build();
But if you don't want to return a StreamingOutput instance, there's other option.
2nd - Define the inputstream as an entity response.
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response download() {
InputStream is = getYourInputStream();
return Response.code(200).entity(is).build();
}

Categories

Resources