PDA

View Full Version : Force download file from server



ezriel
20 Oct 2012, 9:32 AM
i want to force browser to download pdf file from server(java, spring framework). The request comes from extjs 4.1.1 to Spring controller like this:


@RequestMapping(value="/admin/survey/result/export.action", method = RequestMethod.POST)
public void export(
@RequestParam Integer groupId, @RequestParam Integer surveyId, HttpServletResponse response) throws Exception {

File file = new File("c:/raport.pdf");
InputStream is = new FileInputStream(file);
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=\"raport.pdf\"");
// response.setHeader("Cache-Control","must-revalidate, post-check=0, pre-check=0");
// response.setHeader("Pragma", "public");
// response.setHeader("Expires", "0");
IOUtils.copy(is, response.getOutputStream());
response.flushBuffer();

}
}catch (FileNotFoundException e){
logger.info("throwing FileNotFoundException");
}catch (IOException e)
{
logger.info("throwing IOException");
} catch (Exception e) {
logger.error(e.getMessage(),e);
}
}

The firebug shows response


%PDF-1.4
%????
3 0 obj
<</Length 732/Filter/FlateDecode>>stream
x???n?0?w??-?vHI???H????"#??HT$
[email protected]???S??&????l#)Q?b

/6??????s???>?!???sp?v!?????~8w?C????;??1?h??b?5?? y??A<??w?U???g???hH??4???+
??:?gpv-?=l?N,???;?}??g?6????6?h?g???????X4?1??a?t<C??I?
a????7_N?V???[?7?[??7?J?;????? ?H?rI??W$?<?s ?QQ???+??Zn???~???p?6 ??$e1}?l??L??????????2S??;?+?8a\p???\{?e?#?R??m???0??B???? ?6j?:D?E?g???r?=2????7???Z????m&??q]?Z???:????us24???!%e$???xBfd 2?L}?A"?4v=w?^?[??8?????>??????C}??r??RjC?T?
??HAf[???^????%?\}??dK??t!Jr?tJ?>?#?G?????\?K`??9-??K.!Y???KN?e`?J???z????d?L?u????>64y?gr???'?|
?'?+???!,?cS[A??.??E?K?$?U?A??Q??s*?9???iF?1????`/??
endstream
endobj
5 0 obj
<</Parent 4 0 R/Contents 3 0 R/Type/Page/Resources<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]/Font<</F1 1 0 R/F2 2 0 R>>>>/MediaBox[0 0 595 842]>>
endobj
6 0 obj
<</Length 303/Filter/FlateDecode>>stream
x???Mn?0??>??T
[email protected]??3?=Do?)? ?K??(^d??7c???
?/?)?8I?m?????{G??X???\=1v?;?{???8?|?
?7??m??
{??????=mP?l?q?? ??D?8L????x?U
SC????B?5??0??k?8pi?????1i?fQ?g<?mq?J~??&???Zs??'??^x??V????<?W.??(?J%s]???l?Sy??????+?????_+;????????
endstream
endobj
7 0 obj
<</Parent 4 0 R/Contents 6 0 R/Type/Page/Resources<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]/Font<</F2 2 0 R>>>>/MediaBox[0 0 595 842]>>
endobj
1 0 obj
<</BaseFont/Helvetica/Type/Font/Encoding/WinAnsiEncoding/Subtype/Type1>>
endobj
2 0 obj
<</LastChar 241/BaseFont/Times-Roman/Type/Font/Encoding<</Type/Encoding/Differences[32/space 37/percent 40/parenleft/parenright 44/comma/hyphen/period 48/zero/one/two/three/four/five/six/seven 57/nine/colon 63/question 65/A/B/C/D/E 71/G 73/I 78/N/O/P 82/R/S/T 90/Z 97/a/b/c/d/e 103/g/h/i/j/k/l/m/n/o/p 114/r/s/t/u 119/w 121/y/z 140/Sacute 156/sacute 159/zacute 175/Zdotaccent 179/lslash 185/aogonek 191/zdotaccent 230/cacute 234/eogonek 241/nacute]>>/Subtype/Type1/Widths[250 0 0 0 0 833 0 0 333 333 0 0 250 333 250 0 500 500 500 500 500 500 500 500 0 500 278 0 0 0 0 444 0 722 667 667 722 611 0 722 0 333 0 0 0 0 722 722 556 0 667 556 611 0 0 0 0 0 611 0 0 0 0 0 0 444 500 444 500 444 0 500 500 278 278 500 278 778 500 500 500 0 333 389 278 500 0 722 0 500 444 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 556 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 389 0 0 444 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 611 0 0 0 278 0 0 0 0 0 444 0 0 0 0 0 444 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 444 0 0 0 444 0 0 0 0 0 0 500]/FirstChar 32>>
endobj
4 0 obj
<</Type/Pages/Count 2/Kids[5 0 R 7 0 R]>>
endobj
8 0 obj
<</Type/Catalog/Pages 4 0 R>>
endobj
9 0 obj
<</Producer(iText? 5.3.2 ?2000-2012 1T3XT BVBA \(AGPL-version\))/Title(c:/raport-ankieta-botanika-2012-10-19 13-39.pdf)/Subject(raport z ankiety)/ModDate(D:20121019133940+02'00')/CreationDate(D:20121019133940+02'00')>>
endobj
xref
0 10
0000000000 65535 f
0000001507 00000 n
0000001595 00000 n
0000000015 00000 n
0000002646 00000 n
0000000814 00000 n
0000000980 00000 n
0000001350 00000 n
0000002703 00000 n
0000002748 00000 n
trailer
<</Root 8 0 R/ID [<14ea5de4facbc96d8610561e053a931a><424e59355dd4183fbc403a11392e35eb>]/Info 9 0 R/Size 10>>
%iText-5.3.2
startxref
2982
%%EOF

But download window doesn't show up. What am I doing wrong? I tried different content-type:
application/octet-stream
application/pdf
application/force-download

and defferent file attachment:
response.setHeader("Content-Disposition", "attachment;filename=\"raport.pdf\"");
response.setHeader("Content-Disposition", "attachment;filename=raport.pdf");

Extjs code:


text:'Eksport',
tooltip:'Eksportuj zaznaczon? ankiet? do pliku pdf',
iconCls:'edit',
handler: function() {
if(win.down('grid').getSelectionModel().getSelection().length == 1){
var record = win.down('grid').getSelectionModel().getSelection();
Ext.Ajax.request({
url : 'survey/result/export.action',
method: 'POST',
params : { surveyId : record[0].get('surveyId'), groupId: record[0].get('teamId')},
success: function (response) {
// });
},
failure: function (response) {
var jsonResp = Ext.JSON.decode(response.responseText);
Ext.MessageBox.show({
title: 'B??d',
msg: jsonResp.message,
icon: Ext.MessageBox.ERROR,
buttons: Ext.Msg.OK
});
}
});
}
}
}


Thanks

skirtle
20 Oct 2012, 10:26 AM
I don't think you can do a download using an Ajax request, the usual trick is to use a hidden iframe. For a GET request you should just be able to set the iframe src, for a POST you'd need to create a hidden form and submit that to the iframe.

ezriel
20 Oct 2012, 10:33 AM
I don't think you can do a download using an Ajax request, the usual trick is to use a hidden iframe. For a GET request you should just be able to set the iframe src, for a POST you'd need to create a hidden form and submit that to the iframe.

Ok, i am able to send generated file via GET method


{
text:'Eksport',
tooltip:'Eksportuj zaznaczon? ankiet? do pliku pdf',
iconCls:'edit',
handler: function() {
if(win.down('grid').getSelectionModel().getSelection().length == 1){
var record = win.down('grid').getSelectionModel().getSelection();
try {
Ext.destroy(Ext.get('downloadIframe'));
}
catch(e) {}
Ext.DomHelper.append(document.body, {
tag: 'iframe',
id:'downloadIframe',
frameBorder: 0,
width: 0,
height: 0,
css: 'display:none;visibility:hidden;height:0px;',
src: 'survey/result/export.action?surveyId=' + record[0].get('surveyId')+ '&groupId=' + record[0].get('teamId')
});
}
}
}


Can you write example for POST?

skirtle
20 Oct 2012, 11:09 AM
Not convinced this is perfect but it's along the right lines:


MyApp.download = function(config) {
var form,
removeNode = MyApp.download.removeNode,
frameId = Ext.id(),

iframe = Ext.core.DomHelper.append(document.body, {
id: frameId,
name: frameId,
style: 'display:none',
tag: 'iframe'
}),

inputs = paramsToInputs(config.params);

// If the download succeeds the load event won't fire but it can in the failure case. We avoid using Ext.Element on
// the iframe element as that could cause a leak. Similarly, the load handler is registered in such a way as to
// avoid a closure.
iframe.onload = MyApp.download.onload;

form = Ext.DomHelper.append(document.body, {
action: config.url,
cn: inputs,
method: config.method || 'GET',
tag: 'form',
target: frameId
});

form.submit();

removeNode(form);

// Can't remove the iframe immediately or the download won't happen, so wait for 10 minutes
Ext.defer(removeNode, 1000 * 60 * 10, null, [iframe]);

function paramsToInputs(params) {
var inputs = [];

for (var key in params) {
var values = [].concat(params[key]);

Ext.each(values, function(value) {
inputs.push(createInput(key, value));
});
}

return inputs;
}

function createInput(key, value) {
return {
name: Ext.htmlEncode(key),
tag: 'input',
type: 'hidden',
value: Ext.htmlEncode(value)
};
}
};

// Declared outside the download function to avoid a closure
MyApp.download.onload = function() {
// Note we only come into here in the failure case, so you'll need to include your own failure handling
var response = this.contentDocument.body.innerHTML;

...
};

// Declared outside the download function to avoid a closure
MyApp.download.removeNode = function(node) {
node.onload = null;
node.parentNode.removeChild(node);
};

Then:


MyApp.download({
method: 'POST',
params: {...},
url: ...
});

ezriel
20 Oct 2012, 11:25 AM
Thank you @skirtle. It works perfect.

23 Apr 2013, 3:05 AM
Hi All,
Same popup window of save pdf is not opening in my browser.
I tried the code provided in this post but this doesn't work for me.
I'm getting response in pdf format, Any body please help me to solve this issue

Thanks in advance
Sujay