I'm using ExtJs 4.2.3.
In my web application I need to download files.
In order to do that I'm using a 'FileDownloader' component defined as in post
fileDownloader
The code is:
Ext.define('myApp.FileDownload', {
extend: 'Ext.Component',
alias: 'widget.FileDownloader',
autoEl: {
tag: 'iframe',
cls: 'x-hidden',
src: Ext.SSL_SECURE_URL
},
load: function(config) {
var e = this.getEl();
e.dom.src = config.url +
(config.params ? '?' + Ext.Object.toQueryString(config.params) : '');
console.log('in FileDownloader - src: ' + e.dom.src);
e.dom.onLoad = function() {
if(e.dom.contentDocument.body.childNodes[0].wholeText == '404') {
Ext.Msg.show({
title: 'Attachment missing',
msg: 'File cannot be found on the server !',
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.ERROR
});
};
};
}
});
I call it by code:
downloader.load({
url: src
});
where src is complete path to file.
If I download Word, Excel, PDF files it's working well, file reference is visualized in download bar of browser, but with other data types (ex. .txt, .jpg) it doesn't do nothing.
I think it's no a question about Extjs or js, it's the server's reponse. See this download the text file instead of opening in the browser
Related
I am aware that a DOCX file is essentially a zip full of XML files. Is there any simple way of using the chrome.fileSystem storage API to save a DOCX file, or would I have to create and package the XML files manually?
chrome.fileSystem.chooseEntry({
type: 'saveFile',
accepts: [
{ extensions: ['docx'] },
{ extensions: ['txt'] },
]
}, function(writableFileEntry) {
var ext = writableFileEntry.name.substr(writableFileEntry.name.lastIndexOf('.') + 1);
var text = document.getElementById("textarea").innerText;
if(ext == 'docx'){
... ?
}
else if(ext == 'txt'){
writableFileEntry.createWriter(function(writer) {
writer.write(new Blob([text], {type: 'text/plain'}));
}, function(){
window.alert('Saving file failed');
});
}
});
fileSystem API has nothing to do with specific file formats or compression - this is outside its scope. It's providing raw file access.
To do any kind of content formatting, you need to look for extra libraries or do it yourself, and then feed the resulting binary to fileSystem.
Very low-level file upload:
dockedItems: [{
xtype: 'toolbar',
dock: 'top',
items: [{
xtype: 'form',
items: [{
xtype: 'filefield',
fieldLabel: 'Select file',
listeners: {
change: {
fn: me.onFilefieldChange,
scope: me
}
}
}]
},{
...
onFilefieldChange: function(filefield, value, eOpts) {
var form = filefield.up('form').getForm();
form.submit({
url: APIURI+'FileUpload',
headers: {'Accept':'application/json','Content-Type':'application/json'},
waitMsg: 'Uploading',
success: function(fp, o) {
var filedata = Ext.decode(o.response.responseText).data;
var rec = Ext.create("MyApp.model.FileModel",filedata);
Ext.getStore("FileStore").add(rec);
},
failure: function(fp, o) {
Ext.alert("ERROR", "File save failed"));
}
});
The first file upload works like a charm; the file is packed into the multipart/mime and submitted correctly.
The second file upload from the very same file upload field fails, because the file is not packed into the mime.
If I close the window and open it again, the file field is working again - for a single upload, that is.
The difference in DOM of the file input field tells us why the browser behaves like this. The following three attributes are magically missing from the <input type="file" field after the first file upload:
data-ref="fileInputEl"
name="filefield-1333-button"
data-componentid="filefield-1333-button"
Now, this does not happen if I use the file upload field in the sencha docs. It doesn't happen with my code in ExtJS 4.2.2. But it does happen with ExtJS 6.0.1.
You wouldn't know why, would you?
It is a bug in Sencha ExtJS 6 Framework. Everything works as expected if you provide a name property to the file upload field.
xtype: 'filefield',
fieldLabel: 'Select file',
name: 'RequiredSenchaBugWorkaround',
...
Adding a name doesn't always work. It still has issues in Ext 6.2. In addition to that you should do
FileInputField1.reset();
This makes sure that the field is reset and lets you upload the same file again.
The upload tab of image2 plugin looks like this -
{
id: 'Upload',
hidden: false,
filebrowser: 'uploadButton',
label: lang.uploadTab,
elements: [
{
type: 'file',
id: 'upload',
label: lang.btnUpload,
style: 'height:40px',
onChange: function(evt){
alert('file uploaded');
}
},
{
type: 'fileButton',
id: 'uploadButton',
filebrowser: 'info:src',
label: lang.btnUpload,
'for': [ 'Upload', 'upload' ]
}
]
}
Here in the 'tab' details there is filebrowser field which is equal to 'uploadButton' and filebrowser field is also in UI element object where it is equal to 'info:src'.
I am not implementing Browse Server functionality, only upload functionality. I have implemented it but I want to understand how filebrowser plugin and filebrowser fields are facilitating it?
Can anyone here explain here a little bit in detail as CKEditor documentation does not tell much?
The ck_config.js file has settings which determine the URL of the file browser for various purposes:
config.filebrowserBrowseUrl = '';
config.filebrowserImageBrowseUrl = '';
config.filebrowserFlashBrowseUrl = '';
config.filebrowserUploadUrl = '';
config.filebrowserImageUploadUrl = '';
config.filebrowserFlashUploadUrl = '';
Basically this will be a webpage which appears in a roughly 600px-wide popup.
One of the GET parameters of this URL (automatically added) will be CKEditorFuncNum which determines the callback function for sending the results back to CK.
On selection of a file/path, you would typically do:
window.opener.CKEDITOR.tools.callFunction(ck_callback,pathrel2page);
where ck_callback is the CKEditorFuncNum value and pathrel2page is the selected file.
HTH.
I have a form with various textfields and two buttons - Export to Excel and Export to CSV.
The user can provide the values to different fields in the form and click one of the buttons.
Expected behaviour is that an Ajax request should be fired carrying the values of fields as parameters and the chosen file (Excel/CSV as per the button click) should get downloaded (I am not submitting the form as there needs to be done some processing at the values before submit).
I have been using the following code in success function of Ajax request for the download:
result = Ext.decode(response.responseText);
try {
Ext.destroy(Ext.get('testIframe'));
}
catch(e) {}
Ext.core.DomHelper.append(document.body, {
tag: 'iframe',
id:'testIframe',
css: 'display:none;visibility:hidden;height:0px;',
src: result.filename,
frameBorder: 0,
width: 0,
height: 0
});
The above code has been working fine in the case when the file is created physically at the server. But in my current project, the file is not created at the server, rather the contents are just streamed to the browser with proper headers.
Thus, is there a way to download a file using Ajax when the file is not present at the server physically? Just to add that I have a long list of parameters which I need to send to the server and hence can not add them all to the src of iframe.
Could anyone guide at this?
Thanks for any help in advance.
You may use component like this:
Ext.define('CMS.view.FileDownload', {
extend: 'Ext.Component',
alias: 'widget.FileDownloader',
autoEl: {
tag: 'iframe',
cls: 'x-hidden',
src: Ext.SSL_SECURE_URL
},
stateful: false,
load: function(config){
var e = this.getEl();
e.dom.src = config.url +
(config.params ? '?' + Ext.urlEncode(config.params) : '');
e.dom.onload = function() {
if(e.dom.contentDocument.body.childNodes[0].wholeText == '404') {
Ext.Msg.show({
title: 'Attachment missing',
msg: 'The document you are after can not be found on the server.',
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.ERROR
})
}
}
}
});
Put it somewhere in viewport, for example:
{
region: 'south',
html: 'South',
items: [
{
xtype: 'FileDownloader',
id: 'FileDownloader'
}
]
}
Do not forget to require it in your viewport class:
requires: [
'CMS.view.FileDownload'
]
Action handler may look like this:
var downloader = Ext.getCmp('FileDownloader')
downloader.load({
url: '/attachments/' + record.get('id') + '/' + record.get('file')
});
It's very important to have Content-Disposition header in response, otherwise nothing is downloaded.
Regards go to http://www.quispiam.com/blog/post.php?s=2011-06-09-download-a-file-via-an-event-for-extjs4
This thing works for me.
I've got two instances of uploadify in my form. You'll find the definitions below.
And two buttons that trigger the uploads. The image button is the only one relevant to the question:
$( "#btnimageupload" ).button().click(function()
{
$('#picbrowse').uploadifySettings( 'scriptData', ({ 'isSelected': $( '#selectImage' ).val() }));
$('#picbrowse').uploadifyUpload();
});
Now, here's the issue:
When I click btnimageupload button, the image doesn't upload. The progressbar goes to 100 and stops. No errors, javascript or otherwise.
But, when I disable the vdobrowse file input box, and its corresponding script, everything works fine. The images are uploaded and the data is transferring.
Here's the tricky part... if I don't pass the scriptData on the btnimageupload click handler, images will upload even with vdobrowse file input box on the page.
So it seems to me like scriptData is breaking uploadify when there's more than one instance of uploadify on the page.
Anyone know how I could solve this?
Uploadify definitions
$('#picbrowse').uploadify(
{
uploader : 'script/uplodify/uploadify.swf',
script : '../../dopost.php',
cancelImg : 'script/uplodify/cancel.png',
folder : '/images',
queueID : 'picqueue',
auto : false,
multi : true,
fileDesc : 'Image Files',
fileExt : '*.gif;*.jpg;',
queueSizeLimit: 5,
scriptData:
({
'action': 'upload_image',
}),
onComplete: function( event, queueID, fileObj, response, data )
{
console.log( reponse)
}
});
.
$('#vdobrowse').uploadify(
{
uploader : 'script/uplodify/uploadify.swf',
script : '../../dopost.php',
cancelImg : 'script/uplodify/cancel.png',
folder : '/video',
queueID : 'vdoqueue',
auto : false,
multi : true,
fileDesc : 'Video Files',
fileExt : '*.avi;*.mpg;*.mov;*.mp4;*.mpeg;*.flv;*.mkv;*.wmv',
queueSizeLimit: 5,
scriptData:
{
action: 'upload_video'
},
onComplete: function( event, queueID, fileObj, response, data )
{
console.log( response );
}
});
The plugin appears to be putting the
options into global space, which is
why when you are using two or more
uploadify's with scriptData it is
picking up the last stored value in
scriptData.
I see running two uploadify's on one
page a pointless exercise and as such
I never test the functionality with
multiple uploadify's.
uploadifySettings works perfectly with
one uploadify. Multiple uploadify's
are the demo page to demonstrate the
different setups possible.
That said, it is still obviously a
problem for users and we will need to
fix it for those that wish to use
multiple uploadify's on the same page.
Forum
I suggest to use swfUpload. I am use in at my project and tested with multiple instances and it's work perfect. So swfUpload easy to understand and api looks like as uploadify api.
Given that there seems to be a limitation with scriptData and multiple Uploadifys on a page, what you could do is skip the scriptData and folder attributes and parse out the file types inside dopost.php and take an action based on that.
For example:
$fileParts = pathinfo($_FILES['Filedata']['name']);
$extension = strtolower($fileParts['extension']);
switch($extension){
case "gif" | "jpg":
// Do Image Upload Action
break;
case "avi" | "mpg" | "mov" | "mp4" | "mpeg" | "flv" | "mkv" | "wmv":
// Do Video Upload Action
break;
}
I'm receiving the scripData just fine, I've made an example on my website
I've limited the upload size to 500KB for obvious reasons and corrected the code:
$('#picbrowse').uploadify(
{
uploader : 'uploadify.swf',
script : 'uploadify.php',
cancelImg : 'cancel.png',
folder : 'uploads/images',
queueID : 'picqueue',
auto : false,
multi : true,
removeCompleted : false,
fileDesc : 'Image Files',
fileExt : '*.gif;*.jpg',
sizeLimit : 512000,
queueSizeLimit: 5,
scriptData: {action: 'upload_image'},
onComplete: function( event, queueID, fileObj, response, data )
{
$ul.html('');
var json = jQuery.parseJSON(response);
$.each(json,function(k,v){
var li = "<li>"+k+": "+v+"</li>";
$ul.append(li);
});
},
onError: function (event,ID,fileObj,errorObj) {
console.log(errorObj.type + ' Error: ' + errorObj.info);
}
});
$('#vdobrowse').uploadify(
{
uploader : 'uploadify.swf',
script : 'uploadify.php',
cancelImg : 'cancel.png',
folder : 'uploads/video',
queueID : 'vdoqueue',
auto : false,
multi : true,
sizeLimit : 512000,
fileDesc : 'Video Files',
fileExt : '*.avi;*.mpg;*.mov;*.mp4;*.mpeg;*.flv;*.mkv;*.wmv',
queueSizeLimit: 5,
scriptData: {action: 'upload_video'},
onComplete: function( event, queueID, fileObj, response, data )
{
$ul.html('');
var json = jQuery.parseJSON(response);
$.each(json,function(k,v){
var li = "<li>"+k+": "+v+"</li>";
$ul.append(li);
});
}
});
And I'm using the standard uploadify.php and echoing the POST variable instead:
echo json_encode($_POST);