Uploading file using Spring REST API - spring

I have my controller like this, i am using POSTMAN REST client for upload pdf file. setting content-type: multipart/form-data;boundary=randomBoundaryNotInAnyOfParts
It is creating the file but not writing anything in it. Am i missing something here?
#RequestMapping(value = "/uploadfile", method = RequestMethod.POST)
public #ResponseBody String upload(HttpServletRequest request) {
InputStream is = null;
OutputStream out = null;
try {
is = request.getInputStream();
byte[] b = new byte[1024];
out = new FileOutputStream(new File("C:\\tmp\\upload.txt"));
out.write(b);
} catch (IOException e) {
e.printStackTrace();
} finally{
try{
if(out != null){
out.close();
}
if(is != null){
is.close();
}
}catch(IOException io){
io.printStackTrace();
}
}
return null;
}
Thanks,
Vinay

Your byte[] is empty hence it is writing nothing in the file. Get content of the request into the byte[] and then write it into file.
Or you can use BufferedWriter also it is more fast.
Thanks,
Brijesh

Related

I want to upload file without using multipart in spring boot, would be great if I could get you valuable suggestions on this

Shall I remove this from application.properties
spring.http.multipart.enabled=true
What should be my approach towards this file upload without using multipart?
This way, I'm able to uploading file using where I'm using multipart.
#RequestMapping(value = "/dog/create/{name}", method = RequestMethod.POST)
public JsonNode dogCreation(HttpServletRequest httpRequest, #RequestParam(value = "picture", required = false) MultipartFile multipartFile,
#PathVariable("name") String name) throws IOException, InterruptedException {
JSONObject response = new JSONObject();
Dog dog = new Dog();
String DOG_IMAGES_BASE_LOCATION = "resource\\images\\dogImages";
try {
File file = new File(DOG_IMAGES_BASE_LOCATION);
if (!file.exists()) {
file.mkdirs();
}
} catch (Exception e) {
e.printStackTrace();
}
dog = dogService.getDogByName(name);
if (dog == null) {
if (!multipartFile.isEmpty()) {
String multipartFileName = multipartFile.getOriginalFilename();
String format = multipartFileName.substring(multipartFileName.lastIndexOf("."));
try {
Path path = Paths.get(DOG_IMAGES_BASE_LOCATION + "/" + name + format);
byte[] bytes = multipartFile.getBytes();
File file = new File(path.toString());
file.createNewFile();
Files.write(path, bytes);
if (file.length() == 0) {
response = utility.createResponse(500, Keyword.ERROR, "Image upload failed");
} else {
String dbPath = path.toString().replace('\\', '/');
dog = new Dog();
dog.setName(name);
dog.setPicture(dbPath);
dog = dogService.dogCreation(dog);
response = utility.createResponse(200, Keyword.SUCCESS, "Image upload successful");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
return objectMapper.readTree(response.toString());
}
I want to do it without using multipart, what would you suggest?
This is what I've done till now to solve this
#RequestMapping(value = "/dog/create/{name}", method = RequestMethod.POST)
public JsonNode dogCreation(HttpServletRequest httpRequest, #RequestParam("picture") String picture,
#PathVariable("name") String name) throws IOException, InterruptedException {
JSONObject response = new JSONObject();
Dog dog = new Dog();
String DOG_IMAGES_BASE_LOCATION = "resource\\images\\dogImages";
try {
File file = new File(DOG_IMAGES_BASE_LOCATION);
if (!file.exists()) {
file.mkdirs();
}
} catch (Exception e) {
e.printStackTrace();
}
dog = dogService.getDogByName(name);
if (dog == null) {
if (!picture.isEmpty()) {
String dogPicture = picture;
byte[] encodedDogPicture = Base64.encodeBase64(dogPicture.getBytes());
String format = dogPicture.substring(picture.lastIndexOf("."));
try {
} catch (Exception e) {
e.printStackTrace();
}
}
}
return objectMapper.readTree(response.toString());
}
I just have to say that this should probably only be used as a workaround.
On your frontend, convert the file to base64 in js:
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(evt) {
console.log(evt.target.result);
//do POST here - something like this:
$.ajax("/upload64", {
method: "POST",
contentType: "application/text"
data: evt.target.result
}
};
On the server with an example of a decoder - more decoding options here Decode Base64 data in Java
import sun.misc.BASE64Decoder;
#PostMapping("/upload64")
public String uploadBase64(#RequestBody String payload){
BASE64Decoder decoder = new BASE64Decoder();
byte[] decodedBytes = decoder.decodeBuffer(encodedBytes);
//use your bytes
}

download csv using spring boot and apache commons

I have this below code for downloading CSV as an ajax button click, But the file is not downloading. Only showing the black new tab on the browser.
#RequestMapping(value = "/batch/download", method = RequestMethod.POST, produces = "text/csv")
#ResponseBody
public void downloadNGIBatchSelected(HttpServletResponse response) throws IOException {
List<String> ids = Arrays.asList("1312321","312313");
generateNewCustomerCSV(response.getWriter(),ids);
}
private void generateNewCustomerCSV(PrintWriter writer, List<String> ids){
String NEW_LINE_SEPARATOR = "\n";
//CSV file header
Object[] FILE_HEADER = {"Token Number",
"Token Expiry Date",
};
CSVPrinter csvPrinter = null;
try {
csvPrinter = new CSVPrinter(new BufferedWriter(writer), CSVFormat.DEFAULT.withRecordSeparator(NEW_LINE_SEPARATOR));
//Create CSV file header
csvPrinter.printRecord(FILE_HEADER);
for (PolicyMap PolicyMap : policyMaps) {
List customerCSV = new ArrayList();
customerCSV.add(PolicyMap.getInsurancePolicy().getTokenNo());
try {
csvPrinter.printRecord(customerCSV);
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
writer.flush();
writer.close();
csvPrinter.close();
} catch (IOException e) {
System.out.println("Error while flushing/closing fileWriter/csvPrinter !!!");
e.printStackTrace();
}
}
}
You have set the content type in #RequestMapping annotation. But it is not going to work in the case when response is being written using HttpServletResponse. In this case, instead of spring, HttpServletResponse is writing the response that's why you have to set the response type in the response before getting the writer.
response.setContentType ("application/csv");
response.setHeader ("Content-Disposition", "attachment; filename=\"nishith.csv\"");

Should inputstream be closed explicitly when uploading file in jersey multipart?

I use Jersey multipart to upload file in controller
Here is the typical code case:
#Path("/file")
public class UploadFileService {
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetail) {
String uploadedFileLocation = "d://uploaded/" + fileDetail.getFileName();
// save it
writeToFile(uploadedInputStream, uploadedFileLocation);
String output = "File uploaded to : " + uploadedFileLocation;
return Response.status(200).entity(output).build();
}
// save uploaded file to new location
private void writeToFile(InputStream uploadedInputStream,
String uploadedFileLocation) {
try {
OutputStream out = new FileOutputStream(new File(
uploadedFileLocation));
int read = 0;
byte[] bytes = new byte[1024];
out = new FileOutputStream(new File(uploadedFileLocation));
while ((read = uploadedInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I have read many example code online, and the inputstream is not closed.
My question is that should I close the uploadedInputStream explicitly or manually? And why?

Spring MVC Thymeleaf: Displaying Buffered Image to HTML file

Can't display the image in the html file. Where did I go wrong?
#RequestMapping(value = "/image/{usr.id}", headers = "Accept=image/jpeg, image/jpg, image/png, image/gif", method = RequestMethod.GET)
public #ResponseBody BufferedImage getImage(#PathVariable("usr.id") Long id) {
Attachment att = attSvc.getPicById(id);
try {
InputStream in = new ByteArrayInputStream(att.getAttachmentFile());
return ImageIO.read(in);
} catch (IOException e) {
System.out.println("ERROR:" + e);
throw new RuntimeException(e);
}
}
Please tell me if you need more references! Thank you so much.
This should solve your issue.
...
public #ResponseBody byte[] getImage(#PathVariable("usr.id") Long id) {
...
InputStream in = new ByteArrayInputStream(att.getAttachmentFile());
BufferedImage img = ImageIO.read(in);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", bao);
return bao.toByteArray();
...

Spring and serving files from outside of the web server

I want spring to serve certain files from the /tmp... directory, the specific directory isn't determined until shortly after the server starts so using <mvc:resources location="/images/**" mapping="/absolute/path/to/image/dir"/> won't seemingly work.
As Dave Newton noted - stream them from a controller. A very basic implementation:
#RequestMapping("/static/temp/{path}")
public void getResource(#PathVariable path, OutputStream os) {
//TODO proper IO management
InputStream is = new BufferedInputStream(new FileInputStream("/temp/" + path));
IOUtils.copy(is, os);
}
I do something like this:
#RequestMapping(value="/staticFile/{id}", method = RequestMethod.GET)
public void getPhotoRide2(HttpServletResponse response, #PathVariable int id) {
try {
FileInputStream in = new FileInputStream("your file");
OutputStream out = response.getOutputStream();
response.setContentType("your mime type");
byte[] buf = new byte[1024];
int count = 0;
while ((count = in.read(buf)) >= 0) {
out.write(buf, 0, count);
}
in.close();
out.flush();
out.close();
} catch (Exception e) {}
}

Resources