This question already has an answer here:
How to download file from httpServlet with Jquery?
(1 answer)
Closed 5 years ago.
I'm pretty new to jQuery and ajax and i have a question.
In a jsp I call
function downloadDocument(documentId){
var action = "attachment.do";
var method = "downloadDocument";
var url = action + "?actionType="+method+"&documentId=" + documentId;
$.ajax({
url: url,
dataType: "json",
type: 'POST',
success: function(data){
alert("downloaded!");
},
error: function (request, status, error) {
alert(request.responseText);
}
});
then in the servlet I do
public void downloadDocument(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws IOException{
AttachmentActionForm form = (AttachmentActionForm)actionForm;
ServletOutputStream out = response.getOutputStream();
try{
// Get the downloadFileName, the name of the file when it will be downloaded by user
String downloadFileName = "hello.txt";
String mimetype = "application/x-download"
// Get the byte stream of the file
FileInputStream in = new FileInputStream(Global.ATTACHMENTS_SHARED_FOLDER_PATH + downloadFileName);
// Print out the byte stream
byte[] buffer = new byte[4096];
int length;
while ((length = in.read(buffer)) > 0){
out.write(buffer, 0, length);
}
response.addHeader("Content-Disposition", "attachment; filename="+downloadFileName);
response.setHeader("Content-Length", Integer.toString(length));
response.setContentType(mimetype);
in.close();
}
catch(Exception e){
response.setContentType("text/text;charset=utf-8");
response.setHeader("cache-control", "no-cache");
System.out.println(e.getMessage());
out.println(e.getMessage());
}finally{
out.flush();
}
}
But in the ajax function, I never get a success, all the time I get the error message, even if the message is composed by the string inside of the file. What can I do?
Remove your dataType: "json", options and you will see some debug informations.
By the way, there is a jQuery option that meet you need:
$.fileDownload('some/file.pdf')
.done(function () { alert('File download a success!'); })
.fail(function () { alert('File download failed!'); })
Taken from this answer: https://stackoverflow.com/a/9970672/1420186
EDIT:
Your JSP
function downloadDocument(documentId){
var action = "attachment.do";
var method = "downloadDocument";
var url = action + "?actionType="+method+"&documentId=" + documentId;
$.ajax({
url: url,
dataType: "text", // Change dataType to "text"
type: 'POST',
success: function(data){
if (data == "FAIL") {
alert("File not found!");
} else {
window.location.href = data; // Download the file
}
},
error: function (request, status, error) {
alert("The request failed: " + request.responseText);
}
});
}
In your Servlet, if the file is not exists, just return a "FAIL" string, else return the file URL.
Hope that helps.
dont use Ajax call use //use hidden form approach
<form action='../servletname' method='POST' id='formid'>
<input type='hidden' value='' name='name' id='id'/>
<input type='hidden' value=' ' name='name' id='id' />
</form>
on click of button submit form
$('#formid').submit();
in servlet
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment; filename=filnemae.fileformat");
ServletOutputStream out = res.getOutputStream();
write on ouput stream then close or flush
if you are sending large data through post update postsize in server.xml
Related
I have a website with an ongoing webcam stream which should send snapshots of the video stream to my own Java webserver. The snapshot generating and displaying functionality works perfectly on the website. I want to send the snapshot with a jQuery AJAX POST request to my webserver which looks like that:
$.ajax({
type: 'POST',
url: servicePath + "upload",
contentType: 'multipart/form-data',
xhrFields: {withCredentials: false},
headers: {},
data: hidden_canvas.toDataURL('image/png'),
success: function(data, status, xhttp) {
alert(data);
},
error: function() {
alert("Error uploading snapshot file to server!");
}
});
As I mentioned, displaying the hidden_canvas.toDataURL('image/png') inserted in a src attribute of an <img> works perfectly, so it is definitely valid.
My service on the webserver looks as follows:
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadPicture(byte[] imageBytes) {
String uploadedFileLocation = UPLOAD_FOLDER + "test.png";
try {
OutputStream out = new FileOutputStream(new File(uploadedFileLocation));
out.write(imageBytes);
out.flush();
out.close();
} catch (IOException e) {
return Response.status(500).entity("Can not save file<br>" + e.toString()).build();
}
return Response.status(200).entity("success").build();
}
Test.png is created successfully but not a valid png, when I open it, it does not display at all. And the file on the server looks as follows:
What did I miss? Would there be an alternative way to process the image?
Here's my takeSnapshot method. How could I send the file without the toDataURL()? And what for param would I have to expect then on the server side?
function generateSnapshot() {
var video = document.querySelector('#camera-stream');
var hidden_canvas = document.querySelector('#canvas');
var context = hidden_canvas.getContext('2d');
var width = video.videoWidth;
var height = video.videoHeight;
if (width && height) {
hidden_canvas.width = width;
hidden_canvas.height = height;
// Make a copy of the current frame in the video on the canvas.
context.drawImage(video, 0, 0, width, height);
// Turn the canvas image into a dataURL that can be used as a src for our photo.
return hidden_canvas.toDataURL('image/png');
}
}
I finally could make it work. The toBlob suggestion from Kayaman put me on the right track. But I was not able to send the blob as expected, I had to put it into a FormData and thus had to adjust my webservice. The solution looks as follows:
Website Javascript code:
hidden_canvas.toBlob(function(blob) {
var fd = new FormData();
fd.append('fileName', 'testBlob.png');
fd.append('data', blob);
sendAJAXFileUploadRequest(fd);
},'image/png');
function sendAJAXFileUploadRequest(formData) {
$.ajax({
type: 'POST',
url: servicePath + "upload",
xhrFields: {withCredentials: false},
headers: {},
data: formData,
processData: false,
contentType: false,
success: function(data, status, xhttp) {
alert(data);
},
error: function() {
alert("Error uploading snapshot file to server!");
}
});
}
And the Java Webservice:
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadPicture(#FormDataParam("data") byte[] imageBytes, #FormDataParam("fileName") String fileName) {
String uploadedFileLocation = UPLOAD_FOLDER + fileName;
try {
OutputStream out = new FileOutputStream(new File(uploadedFileLocation));
out.write(imageBytes);
out.flush();
out.close();
} catch (IOException e) {
logger.severe("Can not save file (file location: " + uploadedFileLocation + ")");
return Response.status(500).entity("Can not save file<br>" + e.toString()).build();
}
return Response.status(200).entity("success").build();
}
I want to show pdf in new tab after generated it, im using JQuery 1.12.3 and Spring MVC 4.
When i clic to my link, i generate pdf and my ajax method show success but my pdf isnt showed in new tab, what i've forgot ?
i've follewed this posts :
Display PDF in a webpage
Open ResponseEntity PDF in new browser tab
Spring - display PDF-file in browser instead of downloading
I've tried to remove ResponseBody annotation, but i've the same result
Here is my code :
HTML :
<a id="3676274" class="bulletinLink" target="_blank" href="#">Bulletin du 2015-04-30</a>
JQuery :
$(".bulletinLink").click(function(e){
e.preventDefault();
var id = $(this).attr('id');
var oAjax;
var sUrl = sUrlBase + '/generatePdf/'+id;
oAjax = $.ajax({
url: sUrl,
type: 'GET',
cache: false,
data : '',
async : false
});
oAjax.done(function(transport) {
alert("success");
});
oAjax.fail(function(transport) {
alert("fail");
});
});
Java :
#RequestMapping(value = "/generatePdf/{id}", method = RequestMethod.GET)
#ResponseBody
public final ResponseEntity<byte[]> generateWithResponseBody(#PathVariable("id") final int idBulletin
,final HttpServletRequest httpRequete, final HttpServletResponse httpReponse) throws ApplicationException
{
...
HttpHeaders headers = new HttpHeaders();
headers.setContentType( MediaType.parseMediaType( "application/pdf" ) );
String filename = "spring_tutorial.pdf";
headers.setContentDispositionFormData( filename, filename );
headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");
ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(out.toByteArray(), headers, HttpStatus.OK);
return response;
}
The problem is you need to add the file to the HttpServletResponse, and no need to return any value in your method, so use void, adding the file to the response, the browser will handle it correctly
#RequestMapping(value = "/generatePdf/{id}", method = RequestMethod.GET)
#ResponseBody
public final void generateWithResponseBody(#PathVariable("id") final int idBulletin
,final HttpServletRequest httpRequete, final HttpServletResponse reponse) throws ApplicationException
{
//Here retrieve your PDF file
if(file != null) {
String mimeType = URLConnection.guessContentTypeFromName(file.getName());
if (mimeType == null) {
logger.debug("mimetype is not detectable, will take default");
mimeType = "application/pdf";
}
logger.debug("mimetype : {}", mimeType);
response.setContentType(mimeType);
response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getName()));
response.setContentLength((int) file.length());
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
FileCopyUtils.copy(inputStream, response.getOutputStream());
}
}
I've change my jquery function without Ajax like this and it works know :
window.open(sUrl);
Also, for displaying my pdf in the tab and dont download it, i remove this instruction in controller :
headers.setContentDispositionFormData( filename, filename );
I'm trying to implement a Service that automatically starts a download with the requested file.
This is my AJAX call:
function downloadFile(fileName) {
$.ajax({
url : SERVICE_URI + "files/" + fileName,
contentType : 'application/json',
type : 'GET',
success : function (data)
{
alert("done!");
},
error: function (error) {
console.log(error);
}
});
}
and this is my Spring Service method GET:
#RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET)
public void getFile(#PathVariable("file_name") String fileName,
HttpServletResponse response) {
try {
// get your file as InputStream
FileInputStream fis = new FileInputStream( fileName + ".csv" );
InputStream is = fis;
// copy it to response's OutputStream
ByteStreams.copy(is, response.getOutputStream());
response.setContentType("text/csv");
response.flushBuffer();
} catch (IOException ex) {
throw new RuntimeException("IOError writing file to output stream");
}
}
When my client requests the existing file from the server, the AJAX success() method is executed but the file is not even downloading. Am I doing anything wrong?
Don't use ajax, just set window.location.href to the url of the file and set the http content disposition header in your server script to force the browser to save the file.
function downloadFile(fileName) {
window.location.href = SERVICE_URI + "files/" + fileName;
}
I need help with sending xlsx-file from the server back to the client
This is how it worked BEFORE:
JavaScript (click #export_xls button):
export_xls: function(event) {
window.location = ... + this.workspace.query.id + "/export/xls";
}
Java (create xls-file using Apache POI API):
#GET
#Produces({"application/vnd.ms-excel" })
#Path("/{queryname}/export/xls/{format}")
public Response getQueryExcelExport(
#PathParam("queryname") String queryName,
#PathParam("format") #DefaultValue("flattened") String format){
// ...
try {
byte[] doc = olapQueryService.getExport(queryName,"xls","flat"); // file
String name = "file.xls";
return Response.ok(doc, MediaType.APPLICATION_OCTET_STREAM).header(
"content-disposition",
"attachment; filename = " + name).header(
"content-length",doc.length).build();
}
catch (Exception e) {
log.error("Cannot get excel for query (" + queryName + ")",e);
return Response.serverError().build();
}
}
And it worked fine, but now i need to send some data from javascript to the java, then java process it and create xlsx
So, i use ajax to send that data (in json format)...
export_xls: function(event) {
var data = this.workspace.query.result.lastresult();
var url = ... + this.workspace.query.id + "/testexportxls";
$.ajax({
url: url,
type: "POST",
data: JSON.stringify(data),
async: false,
contentType: "application/json"
});
},
...and create my file in java (almost like it was before):
#POST
#Produces({"application/vnd.ms-excel" })
#Consumes(MediaType.APPLICATION_JSON)
#Path("/{queryname}/testexportxls")
public Response setQueryExcelExport(final Object jsonData)
{
Workbook wb = MyFileBuilder.getFile(jsonData);
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
wb.write(bout);
byte[] doc = bout.toByteArray();
String name = "file.xlsx";
return Response.ok(doc, MediaType.APPLICATION_OCTET_STREAM).header(
"content-disposition",
"attachment; filename = " + name).header(
"content-length",doc.length).build();
}
catch (Exception e){
log.error("Error while xlsx-file creating. Exception message: ",e);
return Response.serverError().build();
}
}
But i can't get that file now, because of the ajax, i think.
Do you know some quick solution, with minimum code edits?
Unfortunately, I almost know nothing about Response, or some HttpServletResponse and stuff like that =/
Thank you for your time.
If you were to define a callback function on success, wouldn't that function be able to handle the file?
Seems not, so I'll have a second try: put the JSON in a hidden form input, and POST the form?
Environment: Eclipse running Tomcat v7.0, working with the Stripes framework for Java, and submitting to the service via a JQuery ajax call.
The Javascript:
jQuery( function(){
jQuery('#testForm').submit( function(e) {
e.preventDefault();
var dataString = jQuery('#testInput').val(); // Pulled from a textarea for testing purposes.
var urlString = jQuery('#urlDropdown').val(); // Pulled from a dropdown for testing purposes.
if( (jQuery('#urlId') != "" ) &&
(!isNaN(parseInt( jQuery('#urlId').val() )) ) ){ // Pulled from an input type=text for testing purposes.
urlString += '?id=' + parseInt( jQuery('#urlId').val() );
}
alert("urlString: " + urlString);
jQuery.ajax({
type: "POST",
url: urlString,
data: dataString,
dataType: 'json',
success: function( returnData ) {
jQuery('#content').html(JSON.stringify(returnData));
},
fail: function( returnData ) {
alert("FAIL");
}
});
});
});
The Stripes Interceptor:
#Before(stages=LifecycleStage.BindingAndValidation, on={"setClient"})
private Resolution intercept() {
String rbody = getRequestBody();
log.info("BODY: " + rbody);
this.setBody( rbody );
return null;
}
And the getRequestBody method being used:
protected String getRequestBody(){
StringBuffer body = new StringBuffer();
String line = null;
try {
BufferedReader reader = getContext().getRequest().getReader();
while ((line = reader.readLine()) != null)
body.append(line);
} catch (Exception e) {
log.error("Buffered Reader Failed", e);
e.printStackTrace();
}
log.info("BODY: " + body.toString());
return body.toString();
}
I am using Firebug to test the input, and the post body of the request is indeed filled with meaty json.
The log.info calls there output a completely empty string. If I call up the getContentLength() on the getRequest, it tells me that the content has the appropriate number of characters. But the content itself comes out as null.
I am 99.99% sure that nowhere else in the code is the Request body being consumed. At the moment, this is my only action file in the Stripes framework, as I've removed every single other file.
Somehow, the request body is completely empty. It should be full of meaty json. Help me, Stack Overflow, you're my only hope!
Thanks to the fine people on the Stripes IRC channel, I have an answer! I needed to add in contentType: "application/json", as so:
jQuery.ajax({
type: "POST",
url: urlString,
contentType: "application/json",
data: dataString,
dataType: 'json',
processData: false,
success: function( returnData ) {
jQuery('#content').html(JSON.stringify(returnData));
},
fail: function( returnData ) {
alert("FAIL");
}
});