How to convert collection to csv with jackson in java spring? - spring

I have a problem to convert a java.util.Collection to a csv file with jackson.
In the following code you can see a method to convert the collection to a csv-string.
But i need a method to convert the collection with com.fasterxml.jackson.
The Enum "DownloadType" get the column and headerlines for csv file.
Do you have an idea to fix them?
#RequestMapping(value = "/csv",
produces = {"text/csv"},
consumes = {"application/json"},
method = RequestMethod.POST)
public ResponseEntity<Object> exportCsv()
{
ResponseEntity<Object> response = null;
try
{
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_TYPE, "text/csv; charset=UTF-8");
headers.add(HttpHeaders.CACHE_CONTROL, "no-store, must-revalidate");
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=\"export.csv\"");
headers.add(HttpHeaders.EXPIRES, "0");
byte[] csvBytes = null;
byte[] headerBytes = null;
byte[] lineBytes = null;
CsvMapper mapper = new
Collection<User> users = getUsers()
headerBytes = DownloadType.USER.getHeaderLine().getBytes("UTF-8");
lineBytes = mapper.writer(DownloadType.USER.getCsvSchema()).writeValueAsBytes(users);
if (headerBytes != null && lineBytes != null)
{
csvBytes = new byte[headerBytes.length + lineBytes.length];
System.arraycopy(headerBytes, 0, csvBytes, 0, headerBytes.length);
System.arraycopy(lineBytes, 0, csvBytes, headerBytes.length, lineBytes.length);
}
response = new ResponseEntity<>(csvBytes, headers, HttpStatus.OK);
}
catch (Exception e)
{
LOG.error(e.getMessage(), e);
}
return response;
}

Maybe try something like this. By writing the data directly to the servlet response the string will get returned directly back to the client as is without formatting or post-processing.
#RequestMapping(value = "/csv",
produces = {"text/csv"},
consumes = {"application/json"},
method = RequestMethod.POST)
public void exportCsv(HttpServletResponse response)
{
...
String headerString = DownloadType.USER.getHeaderLine()
String data = mapper.writer(DownloadType.USER.getCsvSchema()).writeValueAsString(users);
response.setContentType("text/plain; charset=utf-8");
response.getWriter().print(headerString);
response.getWriter().print(data);
Adapted from:
How to Return CSV Data in Browser From Spring Controller

Related

Handling multipart response from spring rest controller

I am having controller method like this
#PostMapping(path = "/downloadAttachment",
produces = "application/octet-stream")
public ResponseEntity<?> downloadAttachment(#Valid #RequestBody Attachment attachmentModel) {
refreshProp(false);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
try {
String byteRes = null;
JSONArray responseFromDownloadAttachment =
databaseOperations.downloadAttachment(attachmentModel);
if (responseFromDownloadAttachment.length() == 0) {
return new ResponseEntity<>("", HttpStatus.NO_CONTENT);
}
else {
for (int blobRes = 0; blobRes < responseFromDownloadAttachment.length(); blobRes++) {
JSONObject blobObj = responseFromDownloadAttachment.getJSONObject(blobRes);
if (blobObj != null) {
byteRes = (String) blobObj.getString("file");
}
}
}
byte[] byteArrray = byteRes.getBytes();
return new ResponseEntity<>(byteArrray, HttpStatus.OK);
} catch (Exception e) {
log.error("Exception occurred!" + e);
e.printStackTrace();
JSONObject errObj = new JSONObject();
errObj.put("status", "E");
errObj.put("message", e);
return new ResponseEntity<>(errObj.toString(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
I am sending byte array as response.But i am not sure which type of file i will be getting from service layer.It can be in any form like xlsx,txt,png,jpg or any multimedia.I am setting headers to octet-stream and also produces to octet-stream.Can i use octet-stream to handle these type of responses?

How to Redirect request as post using ResponseEntity

I trying to include response from other url from ResponseEntity for oauth authorization but it is failing as I am unable to specify request method.
Below is the code
#RequestMapping(value = "/login/otp", method = RequestMethod.POST, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
#ResponseBody
public ResponseEntity<?> getOTP(#Valid #RequestBody String loginDtls,UriComponentsBuilder ucBuilder) {
LoginDAO login = null;
ResponseEntity<?> resp = null;
try {
ObjectMapper mapper = new ObjectMapper();
String userId = "";
try {
JsonNode root = mapper.readTree(loginDtls);
userId = root.get("userId").textValue();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("UserController : getting otp for contact "+ userId);
login = loginService.findByUserId(userId);
if (login==null) {
System.out.println("A UserDAO with name " + userId + " does not exist");
resp = new ResponseEntity<String>(HttpStatus.NOT_FOUND);
}
String otp = GenUtil.generateOTP();
LoginDAO loginUpd = new LoginDAO(login);
loginUpd.setOtp(otp);
loginUpd.setOtpTimestamp(new Timestamp(System.currentTimeMillis()));
loginService.updateLogin(loginUpd);
System.out.println(loginUpd);
resp = getAuthenticated(ucBuilder);
System.out.println(resp.getStatusCodeValue());
System.out.println(resp.getBody());
}catch(Exception e) {
e.printStackTrace();
}
resp = new ResponseEntity<String>(login.toString(), HttpStatus.OK);
return resp;
}
private ResponseEntity<?> getAuthenticated(UriComponentsBuilder ucBuilder){
HttpHeaders headers = new HttpHeaders();
URI uri= ucBuilder.path("/oauth/token"+PASSWORD_GRANT).build().toUri();
List<MediaType> accept = new ArrayList<MediaType>();
accept.add(MediaType.APPLICATION_JSON_UTF8);
headers.setAccept(accept);
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
headers.setBasicAuth("my-trusted-client", "secret");
System.out.println(headers);
ResponseEntity<?> resp = ResponseEntity.created(uri).headers(headers).build();
return resp;
}

How to download PDF from Spring REST service using Postman

I have a Spring based Rest service which gives PDF as response. With my below code I can able to get the PDF content as binary values in my postman. My problem is to download it as attachment when I call the service.
To achieve this do i need to make any change in code or in Client.
#GetMapping(value="/getUserpdf")
public ResponseEntity<Resource> getUserInfo(#RequestHeader(name="reqHeader") Map<String, String> reqHeader,
#RequestParam(name="userId",required=true) String userId){
MetaInfo metaInfo = getHeaderValues(reqHeader);
//To get Actual PDF content as Bytes
byte[] pdfBytes = getUserPdfService.getUserInfo(metaInfo,userId);
ByteArrayResource resource = new ByteArrayResource(pdfBytes);
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=UserInfo.pdf");
return ResponseEntity
.ok()
.headers(headers)
.contentLength(pdfBytes.length)
.contentType(MediaType.parseMediaType("application/octet-stream")).body(resource);
}
Also I have registered my Converter
#Bean
public HttpMessageConverters customConverters() {
ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
return new HttpMessageConverters(arrayHttpMessageConverter);
}
Here is an example :
#GetMapping("/getUserpdf/{id}")
#CrossOrigin
#ResponseBody
public ResponseEntity<InputStreamResource> downloadFile(#PathVariable(required = true, value = "id") Long id,#RequestParam(name="userId",required=true) String userId,HttpServletRequest request) throws IOException {
//To get Actual PDF content as Bytes
byte[] pdfBytes = getUserPdfService.getUserInfo(id,userId);
if (Objects.nonNull(pdfBytes)) {
String fileName = "UserInfo.pdf";
MediaType mediaType = MediaType.parseMediaType("application/pdf");
File file = new File(fileName);
FileUtils.writeByteArrayToFile(file, pdfBytes); //org.apache.commons.io.FileUtils
InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
return ResponseEntity.ok()
// Content-Disposition
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + file.getName())
// Content-Type
.contentType(mediaType)
// Contet-Length
.contentLength(file.length()) //
.body(resource);
} else {
throw ResponseEntity.notFound().build();
}
}
NB: i am not sur about the mediaType but you can confirm if it's ok !

POST Multipart file as form data to a REST service

I am trying to POST multipart file as a form data to a REST service which returns me a url after it saved at REST service end. In postman the request look like this.
I have a Spring Boot service which has a method to get Multipart file form frontend via jquery fileuploader. I need to post the file to the above URL which postman sends and saves in there end. I think i have to construct form data in my Spring boot service. Below are few snaps of the Spring boot service.
Controller end.
#RequestMapping(method = RequestMethod.POST, value = "/file-upload/{profileName:.+}")
public Attachment uploadFile(#RequestParam("file") MultipartFile input,
#PathVariable("profileName") String profileName) throws IOException {
Attachment attachment = new Attachment();
if (input != null) {
log.info("Upload a new attachment item" + input.getName());
byte[] fileByteArray = input.getBytes();
attachment.setEncodedFile(Utils.encodeBytes(fileByteArray));
attachment.setFileName(input.getOriginalFilename());
socialMediaService.uploadMedia(input, profileName);
}
return attachment;
}
SocialMediaService
public String uploadMedia(MultipartFile input, String profileName) {
String mediaUploadPath = "wall_attach/lenne-public";
Map < String, String > params = new HashMap < > ();
String mediaUploadFullPath =
UrlBuilder.build(System.getenv(Constants.HUBZILLA_URL), mediaUploadPath, params);
if (!isRestServiceProvided) {
restService = new RestService(RequestType.POST, mediaUploadFullPath);
}
MultipartEntityBuilder builder = restService.getEntityBuilder();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
try {
builder.addBinaryBody("userfile", input.getBytes(), ContentType.DEFAULT_BINARY, input.getOriginalFilename());
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
String strResp = restService.execute(profileName, Constants.HUBZILLA_PW);
return strResp;
}
return null;
}
RestService class
public class RestService {
private Logger log;
private HttpClient client = null;
private HttpRequest request = null;
private RequestType reqType = null;
private String body;
MultipartEntityBuilder builder = null;
public RestService() {
this.log = LoggerFactory.getLogger(RestService.class);
}
/**
* Create REST service with external parameters.
*
* #param reqType RequestType
* #param client HttpClient
* #param request External HttpRequest
*/
public RestService(RequestType reqType, HttpClient client, HttpRequest request, Logger log) {
this.reqType = reqType;
this.client = client;
this.request = request;
this.log = log;
}
/**
* Create REST service string parameters.
*
* #param reqType RequestType
* #param fullPath Full path of REST service
*/
public RestService(RequestType reqType, String fullPath) {
this.client = HttpClientBuilder.create().build();
this.reqType = reqType;
this.log = LoggerFactory.getLogger(RestService.class);
if (reqType == RequestType.GET) {
this.request = new HttpGet(fullPath);
} else if (reqType == RequestType.POST) {
this.request = new HttpPost(fullPath);
} else if (reqType == RequestType.DELETE) {
this.request = new HttpDelete(fullPath);
}
}
/**
* Execute REST service without authentication.
*
* #return - Result of the service.
*/
public String execute() {
return execute(null, null);
}
/**
* Execute REST web service with basic authentication.
*
* #return - Result of the service.
*/
public String execute(String user, String password) {
try {
if (user != null && password != null) {
StringBuilder authString = new StringBuilder();
authString.append(user).append(":").append(password);
String authBase = new String(
Base64.getEncoder().encode(authString.toString().getBytes(Charset.forName("UTF-8"))));
String authType = "Basic ";
String authHeader = authType + authBase;
request.setHeader(HttpHeaders.AUTHORIZATION, authHeader);
}
HttpResponse response = null;
if (this.reqType == RequestType.GET) {
HttpGet get = (HttpGet) request;
response = client.execute(get);
} else if (this.reqType == RequestType.POST) {
HttpPost post = (HttpPost) request;
if (body != null) {
StringEntity stringEntity = new StringEntity(body);
post.setEntity(stringEntity);
}
if (builder != null) {
HttpEntity entity = builder.build();
post.setEntity(entity);
}
response = client.execute(post);
} else {
throw new NotImplementedException();
}
if (response != null && (response.getStatusLine().getStatusCode() == Status.OK.getStatusCode()
|| response.getStatusLine().getStatusCode() == Status.CREATED.getStatusCode())) {
HttpEntity entity = response.getEntity();
return EntityUtils.toString(entity);
}
} catch (Exception e) {
log.error("External service call failed ", e);
}
return null;
}
public void setBody(String body) {
this.body = body;
}
public MultipartEntityBuilder getEntityBuilder() {
this.builder = MultipartEntityBuilder.create();
return this.builder;
}
}
My problem is not getting any result after I executed the rest service upload media method. But it worked perfectly via postman.
Can anybody let me know what am I missing? Is the way I constructed the form data in java correct?
Thank you in advance.
Try adding consumes parameter in #RequestMapping like this (consumes = "multipart/form-data")
#RequestMapping(method = RequestMethod.POST, consumes = "multipart/form-data" ,value = "/file-upload/{profileName:.+}")
public Attachment uploadFile(#RequestParam("file") MultipartFile input,
#PathVariable("profileName") String profileName) throws IOException {
----
----
}
There is another relevant issue here:
Trying to upload MultipartFile with postman
Please read the comments under answer in this link.
Hope it helps!

Spring Restful Mutipart

I would like to ask information regarding Multipart/Form-data, if these are compatible with RequestMethod.GET?
In my case I have to return a file + JSON in one response. (Note: File should not be inside the JSON). Sample response:
FILE
{
"id":"1234",
"name":"question Man"
}
I think this might be helpful, please modify it as of your needs.
#RequestMapping(value = URIConstansts.GET_FILE, produces = { "application/json" }, method = RequestMethod.GET)
public #ResponseBody ResponseEntity getFile(#RequestParam(value="fileName", required=false) String fileName,HttpServletRequest request) throws IOException{
ResponseEntity respEntity = null;
byte[] reportBytes = null;
File result=new File("/filepath/"+fileName);
if(result.exists()){
InputStream inputStream = new FileInputStream("/filepath/"+fileName);
String type=result.toURL().openConnection().guessContentTypeFromName(fileName);
byte[]out=org.apache.commons.io.IOUtils.toByteArray(inputStream);
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add("content-disposition", "attachment; filename=" + fileName);
responseHeaders.add("Content-Type",type);
respEntity = new ResponseEntity(out, responseHeaders,HttpStatus.OK);
}else{
respEntity = new ResponseEntity ("File Not Found", HttpStatus.OK);
}
return respEntity;
}

Resources