Angularjs : call to REST API to get a docx document from server - angularjs

I am trying to call a service from angularjs that produces a docx document.
Angularjs is supposed to display the save prompt of the web browser, and then save the document.
When I open the saved document, what I get in the docx file is :
Undefined
Api rest :
#RequestMapping(value = "/create-avenant",
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public void getAvenant(#RequestBody AvenantDTO avenant, HttpServletResponse response) {
contratService.createAvenant(response, avenant);
}
service produces a XWPFDocument and send to browser :
private void sendDocToBrowser(HttpServletResponse response, XWPFDocument doc) throws IOException {
try
{
byte[] buffer = new byte[8192];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
doc.write(baos);
response.setHeader("Content-Disposition", "attachment;filename=myDoc.docx");
response.setContentType("application/docx");
ServletOutputStream outputStream = response.getOutputStream();
baos.writeTo(outputStream);
outputStream.flush();
}
finally
{
outputStream.close();
}
}
Angularjs :
Avenant.create(avenant,function(result){
var blob = new Blob([result.body], { type: 'application/docx' });
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'file.docx';
link.click();
})

Related

Cannot open downloaded zip file from rest endpoint using file-saver

Here is the backend code for the download endpoint:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ZipOutputStream zipOut = new ZipOutputStream(byteArrayOutputStream);
for (Long id : ids) {
// Get the "generated" file using the id
zipOut.putNextEntry(new ZipEntry(generated.getName() + ".doc"));
InputStream inputStream = new ByteArrayInputStream(generated.getFile().getBytes(1, (int)generated.getFile().length()));
IOUtils.copy(inputStream, zipOut);
zipOut.closeEntry();
}
zipOut.close();
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=File.zip");
byte[] zipBytes = byteArrayOutputStream.toByteArray();
OutputStream outputStream = response.getOutputStream();
outputStream.write(zipBytes);
outputStream.close();
response.flushBuffer();
And for the frontend, I am using axios and file-saver
import { saveAs } from "file-saver";
request.then((response: any) => {
const blob = new Blob([response.data], { type: "application/zip" });
saveAs(blob, "Report.zip");
});
I can download the zip file, but when I tried to open, I got the follwing error:
"An attempt was made to move the file pointer before the beginning of the file"
NOTE: There is no error on the backend. The zip file is downloaded successfully. But upon opening the zip file, the error pops up.
Please, try to rewrite it like that:
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=File.zip");
ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream());
for (Long id : ids) {
// Get the "generated" file using the id
zipOut.putNextEntry(new ZipEntry(generated.getName() + ".doc"));
InputStream inputStream = new ByteArrayInputStream(generated.getFile().getBytes(1, (int)generated.getFile().length()));
IOUtils.copy(inputStream, zipOut);
zipOut.closeEntry();
}
zipOut.close();
response.flushBuffer();

Spring Boot endpoint for downloading File automatically

I want to make a Spring Boot endpoint for downloading file. I Have tried this things but the file does not download automatically... I get only file content in the body...
#RequestMapping(value = "/files", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
#ResponseBody
public ResponseEntity<FileSystemResource> getFile(#RequestParam(name = "start") String start) {
return new ResponseEntity<>(new FileSystemResource(myService.makeFile(start)),
HttpStatus.OK);
}
Another one that I have tried is this:
#RequestMapping(value = "/download", method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public String download(HttpServletResponse response, #RequestParam(name = "start") String start)
{
response.setContentType("application/force-download");
FileReader fr = new FileReader(myService.makeFile(start));
return IOUtils.toString(fr);
}
I have read that MediaType.APPLICATION_OCTET_STREAM_VALUE will force it to download but nothing happened in my case.
You are on the right track, you just need to set one response header Content-Disposition to attachment; filename=YOUR_FILE_NAME.
Try This:
#RequestMapping(value = "/files", method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public FileSystemResource getFile(#RequestParam(name = "start") String start, HttpServletResponse response) {
response.setHeader("Content-Disposition", "attachment; filename=" + "YOUR_FILE_NAME");
return new FileSystemResource(myService.makeFile(start));
}

How to upload file along with json meta data using rest api

I have requirement to upload xlsx file on server along with some json data(both has to be done in one request). I was able to upload just file using multipart/form-data, but when I tried add JSON data to the same request, request is failing with org.apache.commons.fileupload.FileUploadBase$InvalidContentTypeException: the request doesn't contain a multipart/form-data or multipart/mixed stream
exception. Below is my code.
Client side code
var method = 'POST';
$.ajax({
type: method,
url : "rest/file/upload",
transformRequest: function () {
var formData = new FormData();
formData.append("model", JSON.stringify(jsonData));
formData.append("file",document.getElementById("fileForm"));
return formData;
},
enctype : 'multipart/form-data',
processData : false,
contentType : false,
success: function (data) {},
error: function (data) {}
});
model is the JSON data & file is xlsx file which is to be uploaded.
Server Side Code
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.TEXT_PLAIN)
public Response uploadResumableISOFile(#Context HttpServletRequest request, #Context UriInfo uri,
#Context HttpHeaders headers, #Context HttpServletResponse response) throws IOException {
ServletFileUpload uploader = null;
try {
DiskFileItemFactory fileFactory = new DiskFileItemFactory();
uploader = new ServletFileUpload(fileFactory);
List<FileItem> fileItemsList = uploader.parseRequest(request);
Iterator<FileItem> fileItemsIterator = fileItemsList.iterator();
while (fileItemsIterator.hasNext()) {
FileItem fileItem = fileItemsIterator.next();
File file = File.createTempFile("TEMP_", ".xlsx");
fileItem.write(file);
System.out.print("File " + fileItem.getName() + " uploaded successfully.");
}
System.out.println("File uploaded to successfully...");
return Response.status(Response.Status.OK).build();
} catch (Exception e) {
System.out.println(e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("Failed to upload file.").build();
}
}
Please let me know if something is missing.

How to display images in web page using angularjs?

I already know how to save images in mongodb using angularjs and java to save it in my mongodb,
I need to get the saved image from mongodb and display it in an html page using AngularJS.
This is my controller for getting image
#GET
#Path("/{id}")
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getById(#PathParam("id") String id) throws IOException
{
Response response = null;
MongoClient mongoClient = new MongoClient("localhost", 27017);
DB mongoDB = mongoClient.getDB("sampleDB");
DBCollection collection = mongoDB.getCollection("filestore");
BasicDBObject query = new BasicDBObject();
ObjectId oid = new ObjectId(id);
query.put("_id", oid);
GridFS fileStore = new GridFS(mongoDB, "filestore");
GridFSDBFile gridFile = fileStore.findOne(query);
InputStream in = gridFile.getInputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream();
int data = in.read();
while (data >= 0)
{
out.write((char) data);
data = in.read();
}
out.flush();
ResponseBuilder builder = Response.ok(out.toByteArray());
builder.header("Content-Disposition", "attachment; filename=");
response = builder.build();
return response;
}
This is my angularjs for getting image
var userImagePromise = $http.get("../api/s3/" + $scope.user.profileImage[0].id);
userImagePromise.success(function(data, status, headers, config) {
$scope.imageData = data;
});
userImagePromise.error(function(data, status, headers, config) {
});
This is my html for displaying image
<img id="userProfileImg" height="150px" width="150px" ng-src="data:image/png;base64,{{imageData}}">
if I simply put the link to browser i got this output in octect-stream
�PNG .....
How to display image in html?Any error in my code wise?
Image for getting output
i think your base64 code is not converting images properly, so check my code it may help you.
import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import javax.imageio.ImageIO;
BufferedImage buffimage = ImageIO.read(new File(imagePath));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(buffimage, "png", baos);
String img = Base64.encode(baos.toByteArray());
send this img variable to your angularjs code.

How to open Rest API Post response in New window using Angular Js

I am making a rest API call using Angular. My Rest API look like as below:
#RequestMapping(value = "/getPDF/{projectId}", method = RequestMethod.POST)
public ResponseEntity<byte[]> generateReport(#PathVariable("projectId") long projectId, #RequestBody Object vo, final HttpServletRequest request) {
vo.setProjectId(projectId);
byte[] pdf = blueprintService.generateBluePrint(vo);
LOG.debug(new StringBuilder("Generating Blueprint for VO: ").append(vo).toString());
String fileName = null;
try {
ProjectDetailsVO pdvo = projectSetupService.getProjectDetails(vo.getProjectId());
fileName = new StringBuilder(pdvo.getClientName()).append("_")
.append(pdvo.getProjectName()).append("_")
.append(System.currentTimeMillis()).append(".pdf")
.toString();
} catch (Exception e) {
}
if (fileName == null || fileName.trim().isEmpty())
fileName = new StringBuilder("Project_")
.append(vo.getProjectId()).append("_")
.append(System.currentTimeMillis())
.append(".pdf").toString();
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/pdf");
String userAgent = request.getHeader("User-Agent");
if (userAgent != null && !(userAgent.contains("Firefox") && userAgent.contains("Mac"))) {
LOG.debug("Inline BP Content");
headers.add("Content-Disposition", new StringBuilder("inline; filename=\"").append(fileName).append("\"").toString());
} else {
LOG.debug("Attached BP Content");
headers.add("Content-Disposition", new StringBuilder("attachment; filename=\"").append(fileName).append("\"").toString());
}
if (pdf != null)
headers.setContentLength(pdf.length);
return new ResponseEntity<byte[]>(pdf, headers, HttpStatus.OK);
}
}
So server is setting file name for the PDF which I want to be the name of the generated PDF.
I tried below angular code:
success: function (data, status, headers, config) {
$modalInstance.close();
var file = new Blob([data], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
}
It works fine but it open the pdf of it's own name. Which I think, since Angular is converting the response into PDF. Hence Headers are getting excluded.
Is there any way to make a post request so it will open a PDF in new browser tab some code like as below:
$http.post{
url: myRestURL,
data: postbodyData,
taget: _blank
}
which will open my rest URL in new tab and show the PDF in browser.
Thank you.

Resources