I am able to create the file but not able to download it. I am trying to download the file by an ajax call. I am able to receive the file name and file content and successfully able to write the content in a file in application directory but I'm not able to download that file. My code is given bellow :-
The Ajax Code -:
downloadButton.onclick = function() {
//alert(payLoadID);
$.ajax({
type: "POST",
url: "payloadAjax",
data: { payloadData: document.getElementById("modal_paragraph").innerHTML, id: payLoadID },
success : function(data) {
alert("SUCCESS: " +data);
// modal.style.display = "none";
// $("body").css("overflow","auto");
},
error : function(e) {
alert("ERROR: "+ e);
},
done : function(e) {
alert("DONE");
}
})
}
Here is the java code -:
#RequestMapping(value = "/payloadAjax", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE)//, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public #ResponseBody
void download(#RequestParam("payloadData") String payloadData, #RequestParam("id") String fileName, HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("id : " +fileName);
System.out.println("payloadData : " +payloadData);
/* File creation code is here. */
String FOLDER = "/downloadDir";
String FILE_NAME = fileName +".txt";
String appPath = request.getRealPath("");
System.out.println("appPath = " + appPath);
File downloadDirectory = new File(appPath + FOLDER);
if(!downloadDirectory.exists() || !downloadDirectory.isDirectory()) {
downloadDirectory.mkdir();
System.out.println("Directory Created");
} else {
System.out.println("Directory already exists.");
}
File uploadFile = new File(downloadDirectory, FILE_NAME);
if(uploadFile.exists()) {
uploadFile.delete();
System.out.println(uploadFile.getName() +" Has been deleted.");
}
try {
uploadFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("New File successfully created.");
try
{
PrintWriter writer = new PrintWriter(uploadFile, "UTF-8");
writer.println(payloadData);
writer.flush();
writer.close();
System.out.println("File successfully written.");
}
catch(Exception ex) {
ex.printStackTrace();
}
if (uploadFile.exists()) {
System.out.println("Upload file exists. Ready to download....");
} else {
System.out.println("Sorry File not found!!!!");
}
/*File creation code successfully completed.*/
/*File download code starts here */
/*HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_HTML);
headers.setContentLength(uploadFile.length());
headers.setContentDispositionFormData("attachment", "Soubhab_Pathak.txt");
InputStreamResource isr = new InputStreamResource(new FileInputStream(uploadFile));
return new ResponseEntity<InputStreamResource>(isr, headers, HttpStatus.OK);*/
if(response == null) {
System.out.println("Response is null.");
} else {
System.out.println("Response is not null.");
}
System.out.println("111");
OutputStream out = response.getOutputStream();
System.out.println("112");
FileInputStream in = new FileInputStream(uploadFile);
System.out.println("113");
response.setContentType(MediaType.TEXT_PLAIN_VALUE);
response.setHeader("Content-Disposition", "attachment; filename=" + FILE_NAME);
response.setHeader("Content-Length", uploadFile.length() +"");
FileCopyUtils.copy(in, out);
System.out.println("114");
response.flushBuffer();
System.out.println("115");
/*File download code completes here.*/
}
The log is as follows
Any idea?
Finally I am able to solve the problem. This also an example of how to download a string as file in Spring MVC using ajax. Solution is as follows -:
1) one controller action to receive the string from ajax call and store that string in a file in the application server.
2) another controller action where you need to write file download code and this action will receive a GET request.
3) in the ajax call in the success part just call the second action method to download the file.
Now the code is working fine.
Related
I'm using the following solution to try and receive an image in a restful webservice written in java:
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.TEXT_PLAIN)
public String getFile(#FormDataParam("pic") InputStream file,
#QueryParam("uid") String uid) {
try {
storeFile(file, uid);
} catch (IOException ex) {
Logger.getLogger(UploadImage.class.getName()).log(Level.SEVERE, null, ex);
return "failed";
}
return "success";
}
private void storeFile(InputStream input, String uid) throws IOException {
String absPath = PATH_TO_FILES + uid + ".jpg";
try {
OutputStream out = new FileOutputStream(new File(absPath));
int read = 0;
byte[] bytes = new byte[1024];
out = new FileOutputStream(new File(absPath));
while ((read = input.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Here is the client code (javascript):
$scope.fileSelect = function (files) {
var file = files[0];
console.log("File loaded");
console.log(files);
console.log('uid = ' + $scope.uid + ' user = ' + $scope.user);
var formData = new FormData();
formData.append('pic', file);
var requestBody = {"token": $scope.token};
var req = {
method: 'POST',
url: 'http://192.168.0.9/resources/UploadPicture?uid=' + $scope.uid,
headers: {
'Content-Type': undefined
},
data: formData
};
console.log(FormData);
$http(req).then(function(response){
console.log(response);
}, function(error){
console.log(error);
});
};
This code produces a file that isnt viewable. The files im expecting are images.
So i got 2 questions:
Whenever the webservice gets called an a response is return, it seems like the image isnt fully flushed to the harddisk. After a while i can edit it. Is there a way to respond back to the client when the image is actually flushed to the disk?
How can i get the input stream to produce a viewable image when its written to the disk?
--edit--
After some fiddling with the file, i realized if i edit the image in notepad++ and took off the beggining and ending tags for the form boundaries, the image is viewable again:
Produced File
Is there a way for the form boundaries to stop interfering with the image data?
I found a solution using apache commons fileupload:
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.TEXT_PLAIN)
public String getFile(#Context HttpServletRequest request, #QueryParam("uid") String uid) {
ServletFileUpload upload = new ServletFileUpload();
try {
FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext()) {
FileItemStream item = iter.next();
String name = item.getFieldName();
InputStream stream = item.openStream();
if (item.isFormField()) {
System.out.println("Form field " + name + " with value "
+ Streams.asString(stream) + " detected.");
} else {
System.out.println("File field " + name + " with file name "
+ item.getName() + " detected.");
// Process the input stream
storeFile(stream, uid);
}
}
return "success";
} catch (FileUploadException ex) {
Logger.getLogger(UploadImage.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(UploadImage.class.getName()).log(Level.SEVERE, null, ex);
}
return "failed.";
}
I am trying to download file using spring code and my code are running but there is no file downloaded in download folder. here my code are:-
#RequestMapping(value="/downloadRecordFile/{id}",
method = RequestMethod.GET,produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public void downloadRecordFile(#PathVariable("id") Long id,HttpServletRequest request,HttpServletResponse response) throws IOException {
File fileName = new File("C:\workarea\UplodedRecords\test_annotation.pdf");
if (fileName != null) {
if (!fileName.exists()) {
String errorMessage = "Sorry. The file you are looking for does not exist";
log.info(errorMessage);
OutputStream outputStream = response.getOutputStream();
outputStream.write(errorMessage.getBytes(Charset.forName("UTF-8")));
outputStream.close();
return;
}
String mimeType = URLConnection.guessContentTypeFromName(fileName.getName());
if (mimeType == null) {
mimeType = "application/octet-stream";
}
log.info("mimetype : " + mimeType);
response.setContentType(mimeType);
response.setHeader("Content-Disposition", String.format("inline; filename=\"" + fileName.getName() + "\""));
response.setContentLength((int) fileName.length());
InputStream inputStream = new BufferedInputStream(new FileInputStream(fileName));
//Copy bytes from source to destination(outputstream in this example), closes both streams.
FileCopyUtils.copy(inputStream, response.getOutputStream());
inputStream.close();
response.getOutputStream().flush();
}
}
}
My code is not givivng error or exception but it was not downloading file.
angular 2 code:-
function downloadRecord() {
alert("Downloading");
var record_id = 1234;
downloadRecordFile.query({id: record_id}, onSuccess);
}
here is my service js
(function() {
'use strict';
angular
.module('testApp')
.factory('downloadRecordFile', downloadRecordFile);
downloadRecordFile.$inject = ['$resource'];
function downloadRecordFile($resource) {
var resourceUrl = 'api/downloadRecordFile/:id';
return $resource(resourceUrl, {}, {
'query': { method: 'GET', isArray: true},
'get': {
method: 'GET',
transformResponse: function (data) {
if (data) {
data = angular.fromJson(data);
}
return data;
}
}
});
}
})();
Is there any error in code please help me.
I have this web service for file download from email (I provide URL for download):
#Override
#PreAuthorize("hasRole('ROLE_ADMIN')")
#RequestMapping(value = { "download"}, method = RequestMethod.GET)
public void downloadFile(HttpServletResponse response, #RequestParam(value="filePath", required = true) String filePath) {
try{
File file = new File(filePath);
if (file.isFile()){
try(InputStream is = new FileInputStream(file.getAbsolutePath())){
setResponse(response, is, file, "attachment; filename=");
}catch (Exception e1){
ErrorResponse errorResponse= ErrorResponseBuilder.buildErrorResponse(e1);
LOG.error("Threw exception in FleetAndCarControllerImpl::downloadStatisticalFile :" + errorResponse.getStacktrace());
}
}else{
//TODO write that file is not present
}
}catch (Exception e) {
ErrorResponse errorResponse= ErrorResponseBuilder.buildErrorResponse(e);
LOG.error("Threw exception in FleetAndCarControllerImpl::downloadStatisticalFile :" + errorResponse.getStacktrace());
}
}
and setResponse method:
private void setResponse(HttpServletResponse response, InputStream is, File file, String useOfFile) throws Exception{
response.setHeader("Expires", "0");
response.setHeader("Cache-Control","must-revalidate, post-check=0, pre-check=0");
response.setContentType(Files.probeContentType(file.toPath()));
response.setHeader("Content-Description"," File Transfer");
response.setHeader("Content-Disposition", useOfFile + file.getName());
response.setHeader("Content-Transfer-Encoding"," binary");
long size = Utils.stream(is, response.getOutputStream());
response.addHeader("Content-Length", Long.toString(size));
response.flushBuffer();
}
It works fine when file exists, now I would like to write a message if file doesn't exist because now the user views a blank white page and it doesn't know what is happening.
Can you help me?
You could do something like:
response.sendError(HttpServletResponse.SC_NOT_FOUND, "File was not found");
Or better send a redirect to a page with an error message/explanations on what to do next.
I am returning a temporary file from my JAX-RS REST Service like below:
#GET
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getFile() {
File file = ... // create a temporary file
return Response.ok(file, MediaType.APPLICATION_OCTET_STREAM)
.header("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"" ) //optional
.build();
}
What is the correct way of removing this temporary file after the response has been processed? Is the JAX-RS implementation (like Jersey) supposed to do this automatically?
You can pass an instance of StreamingOutput that copies the content of the source file to the client output and eventually deletes the file.
final Path path = getTheFile().toPath();
final StreamingOutput output = o -> {
final long copied = Files.copy(path, o);
final boolean deleted = Files.deleteIfExists(path);
};
return Response.ok(output).build();
final File file = getTheFile();
return Response.ok((StreamingOutput) output -> {
final long copied = Files.copy(file.toPath(), output);
final boolean deleted = file.delete();
}).build();
The example on https://dzone.com/articles/jax-rs-streaming-response looks more helpful than the brief reply from Jin Kwon.
Here is an example:
public Response getDocumentForMachine(#PathParam("custno") String custno, #PathParam("machineno") String machineno,
#PathParam("documentno") String documentno, #QueryParam("language") #DefaultValue("de") String language)
throws Exception {
log.info(String.format("Get document. mnr=%s, docno=%s, lang=%s", machineno, documentno, language));
File file = new DocFileHelper(request).getDocumentForMachine(machineno, documentno, language);
if (file == null) {
log.error("File not found");
return Response .status(404)
.build();
}
StreamingOutput stream = new StreamingOutput() {
#Override
public void write(OutputStream out) throws IOException, WebApplicationException {
log.info("Stream file: " + file);
try (FileInputStream inp = new FileInputStream(file)) {
byte[] buff = new byte[1024];
int len = 0;
while ((len = inp.read(buff)) >= 0) {
out.write(buff, 0, len);
}
out.flush();
} catch (Exception e) {
log.log(Level.ERROR, "Stream file failed", e);
throw new IOException("Stream error: " + e.getMessage());
} finally {
log.info("Remove stream file: " + file);
file.delete();
}
}
};
return Response .ok(stream)
.build();
}
I have a little problem when I try to download a file with rest.
Here is my function :
#GET
#Produces(MediaType.APPLICATION_OCTET_STREAM)
#Path("{directory: (([^/]+[/])+)[^/]+}")
public Response getFile(#PathParam("directory") String directory)
{
Response responseFile = null;
try
{
/*String tmpFileName = "REST_FTP_TMPFile_"+ Math.random();
tmpFileName = tmpFileName.replace(".", "");
File tmpFile = new File(tmpFileName);
tmpFile.createNewFile();
//*/
String filename = directory.substring(directory.lastIndexOf("/")+1, directory.length());
File tmpFile = File.createTempFile("REST_FTP_TMPFile_", null);
directory = StringEscapeUtils.unescapeHtml4(directory);
this.client.getFile(directory, tmpFile);
System.out.println("size : " + tmpFile.length());
responseFile = Response.ok(tmpFile, MediaType.APPLICATION_OCTET_STREAM)
.header("Content-length", tmpFile.length())
.header("Content-Disposition","attachment; filename="+filename+"")
.build();
//A voir quand on peut le supprimer...
//tmpFile.delete();
}
catch (IOException ex)
{
Logger.getLogger(GetResource.class.getName()).log(Level.SEVERE, null, ex);
}
return responseFile;
}
The function getFile of client use the libapache method :
public boolean getFile(String pathname, File file) throws IOException
{
OutputStream output;
output = new FileOutputStream(file);
System.out.println("Wanted pathname : "+pathname);
boolean status = this.client.retrieveFile("/"+pathname, output);
if(status)
{
output.close();
return status;
}
else
{
output.close();
throw new IOException("Cannot retrieve the file : " + pathname);
}
}
When I try to download my web browser says that the download is canceled :
I really don't know what I did wrong and nothing on the web helped me out so far (it's been 2 hours..)
I found what the problem was, the FTP transfer is supposed to be in binary mode..