There is a great multiple-file upload script out there, totally flash free:
http://valums.com/ajax-upload/
Now, while it works for me, I'd like some code to be executed when the upload is done. I think the script provides this functionality, in examples it has this:
onComplete: function(id, fileName, responseJSON){}
but I'm not sure how I'd use it - I just need to have some code executed after the upload is successfully finished.
Sorry if it's a script-specific question, looked to me like it may be general js knowledge.
The {} denotes the function body. Here it is expanded:
onComplete: function(id, fileName, responseJSON){
//this is where you do something on completion.
//you have access to the id, the filename and the JSON.
}
So, for example:
var uploader = new qq.FileUploader({
element: document.getElementById('file-uploader'),
action: '/server-side.upload',
// additional data to send, name-value pairs
params: {
param1: 'value1',
param2: 'value2'
},
onComplete: function (id, fileName, responseJSON) {
alert(fileName + ' was successfully uploaded');
}
});
When it has completed, uploader will execute the onComplete function, passing in the id, filename and JSON.
Related
I'm trying to figure out a way how to rename file after upload using dropzone.js so I could later delete it just by sending correct name.
What I have right now:
this.on("success", function(file, responseText) {
console.log(responseText); // responseText contains actual file name after server modifications
});
addRemoveLinks: true,
this.on("removedfile", function(file) {
var name = file.name;
$.ajax({
type: 'POST',
url: 'delete_file.html',
data: {
'file-name': name,
},
});
});
As you can see in my ajax data I am sending initial file name, not the one that is actually on the server (e.g. if there are multiple same named files server will rename them).
I have been thinking of changing previewElement name on success:
file.previewElement.querySelector(".name").textContent = responseText;
and then refer to this in ajax, but it doesn't look like an elegant approach.
Other alternative would be to create a map with <file, new_name> mapping, but I'm not sure if that's not an overkill.
How would you recommend accessing new file name after upload?
The cleanest option I came up with is using file.xhr.response value which hold the new name instead of file.name
I've successfully implemented the uploading of directory structures with Fine Uploader using the dragAndDrop: reportDirectoryPaths option. Each file that is uploaded has it's qqpath property to signify the path from which it came.
var exampleUploader = new qq.FineUploader({
element: document.getElementById('fine-uploader'),
template: 'qq-template-manual-trigger',
request: {
endpoint: '/api/UploadDocuments',
params: {
param1: "Test1",
param2: "Test2"
}
},
callbacks: {
onComplete: function (id, name, responseJSON, xhr) {
console.log("onComplete");
},
onAllComplete: function (id, name, responseJSON, xhr) {
console.log("onAllComplete");
}
},
multiple: true,
dragAndDrop: {
reportDirectoryPaths: true
},
autoUpload: true,
debug: false
});
There is however, one problem: the files are uploaded one by one, but the ajax request is called sometimes at the same time. If two files with the same directory structure are passed to the service at the exact same time, the directories might be created twice in one go. Is there a way to only do the ajax request on success of the previous? In other words, is there a way to upload the files sequentially, rather than at the same time (a whole bunch of files being passed into the service at once)?
Thanks in advance,
aj
The problem you are seeing is an issue with your server, and not with anything client/browser-side. It's shortsighted to limit your frontend to one request at a time. This presents a completely unnecessary bottleneck. Your server should sort all of this out.
On approach is to keying uploaded files by the UUID assigned by Fine Uploader and then sort out the storage hierarchy later. And if you don't want to trust the UUID supplied by Fine Uploader, you can always generate your own server-side, return it with the response, and Fine Uploader will use that for all other requests related to that specific file instead.
Another approach is for your server to simply check server side to see if the directory already exists for the target file.
Keep in mind that this "qqPath" property you are depending on only exists in Chrome/Opera, and only when a directory is dropped.
If you want to upload files one by one using fine uploader the easiest way is limiting the max connections to 1.
var exampleUploader = new qq.FineUploader({
element: document.getElementById('fine-uploader'),
template: 'qq-template-manual-trigger',
request: {
endpoint: '/api/UploadDocuments',
params: {
param1: "Test1",
param2: "Test2"
}
},
callbacks: {
onComplete: function (id, name, responseJSON, xhr) {
console.log("onComplete");
},
onAllComplete: function (id, name, responseJSON, xhr) {
console.log("onAllComplete");
}
},
maxConnections: 1,
multiple: true,
dragAndDrop: {
reportDirectoryPaths: true
},
autoUpload: true,
debug: false
});
By default the parameter maxConnections is 3.
I've been beating my head over this for quite a while now, so I think it's time I reach out for help. I have some already existing code that uses the jQuery File Uploader plugin, allowing me to upload files to my webserver. The trouble I am having is listing files that already exist on the web server.
Here is my initialization code that runs at the client:
$('#fileupload').fileupload({
disableImageResize: false,
url: '/api/upload',
done: function (e, data) { // data is checked here }
});
// Load existing files:
$('#fileupload').addClass('fileupload-processing');
$.ajax({
url: $('#fileupload').fileupload('option', 'url'),
dataType: 'json',
context: $('#fileupload')[0],
data: { action: "FileList", blob: "uts", path: "Unit 14/Binaries/" }
}).always(function (e, data) {
$(this).removeClass('fileupload-processing');
}).done(function (result) {
$(this).fileupload('option', 'done')
.call(this, $.Event('done'), { result: result });
});
Now, I am trying to return a list of pre-existing files on the server side that matches the JSON response akin to the documentation. My ASP.NET code on the server side is as follows (with two bogus files called "Something" and "SomethingElse" using my FilesStatus class).
// Get a list of files from
private void FileList(HttpContext hc)
{
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
List<FilesStatus> fs_list = new List<FilesStatus>();
fs_list.Add(new FilesStatus("Something", 124));
fs_list.Add(new FilesStatus("SomethingElse", 124));
HttpContext.Current.Response.AddHeader("Pragma", "no-cache");
HttpContext.Current.Response.AddHeader("Cache-Control", "private, no-cache");
hc.Response.AddHeader("Content-Disposition", "inline; filename=\"files.json\"");
var result = new { files = fs_list.ToArray() };
hc.Response.Write(serializer.Serialize(result));
hc.Response.ContentType = "application/json";
HttpContext.Current.Response.StatusCode = 200;
}
In the "done" function of the AJAX code, I see what I believe is the proper response on the client side. Here, you can see the format in my Javascript debugger (i.e., a top level "files" that is an array):
These files do not get populated in to the file list, though. The code that I marked "//data is checked here" in the main done() function shows that the array can be accessed as "data.result.files" NOT "data.files." I can change ".call(this, $.Event('done'), { result: result });" to ".call(this, $.Event('done'), { files: result.files });" so that "data.files" is the location of the file array, but this does not solve the problem. I can't seem to get any pre-existing files to load in to the list.
Does anyone see what I am doing wrong? Happy holidays.
What happens when you change the line:
hc.Response.Write(serializer.Serialize(result));
into
hc.Response.Write(serializer.Serialize(fs_list.ToArray()));
It looks like the serializer is taking the variable name into account when you are serializing your file descriptions. The 'result' JSON object should disappear from the response.
I was overwriting the done() method where I have:
done: function (e, data) { // data is checked here }
I did this for debugging, but apparently it blocks the pre-existing file list from being loaded and calling the download template.
I've got the following ajax call:
var blind = Ext.create('MyApp.view.blind.Progress', {});
blind.show();
Ext.Ajax.request({
url: config.url,
params: {
nodeId: config.data[0].value,
fileName: config.data[1].value,
startDateTime: config.data[2].value,
endDateTime: config.data[3].value,
reportFormat: config.data[4].value
},
success: function (response) {
console.log(response);
blind.close();
}
});
I want to display a blind with a loading graphic, and close it upon completion. Is there any way to use this ajax callback to download the file from the response? Am I on the right track? I would like to avoid using iframes or opening new tabs if possible. I'm open to using other libraries like jquery if it's easier.
Don't think its possible to respond with a file to an ajax request. a simple form submit should do the trick.
Well I don't like being told what I can't do so I kept researching and found this jquery plugin. It works by polling a cookie made by the server when the file is delivered, and the typical iframe method for downloading files. No bloat, no flash, exactly what I was looking for:
Jquery File Download
Download the plugin, link it somewhere in your site, and add this cookie generation code to wherever your file request is going (there are more examples at the link, I'm using ASP.NET):
HttpContext.Current.Response.SetCookie(new HttpCookie("fileDownload", "true") { Path = "/" });
Sample code from my app, using the success and fail callbacks of the plugin to control my extjs blind:
$.fileDownload(config.url, {
successCallback: function (url) {
//Show a message here or perform some task
blind.close();
},
failCallback: function (html, url) {
blind.close();
alert("The report generation failed.");
},
httpMethod: "POST",
data: {
nodeId: config.data[0].value,
fileName: config.data[1].value,
startDateTime: config.data[2].value,
endDateTime: config.data[3].value,
reportFormat: config.data[4].value
}
});
I've got a User model that gets POSTed to the server to create a user on the system. The response is basically:
{
success: false,
message: "User already exists"
}
Cool, within my model I have a REST Proxy. The proxy has a JSONReader attached to it as well with the following:
messageProperty: 'message',
successProperty: 'success'
so I create my user and save it with something like:
var user = Ext.create('App.model.User', {name: "Bill"});
user.save(function (records, operation) {
console.log(records);
console.log(operation);
});
But I can't see anywhere to grab the error message that was returned from the server. All I can grab is: isSuccessful() which seems to correctly say false.
There doesn't seem to be ANYTHING in the documentation about this. I can't understand why something like this isn't included or how I'm missing it.
operation.getResponse(); returns null as well. I've also tried passing in a config with success, failure and callback... seems to be nothing there for me
Thanks, Dom
Try operation.getResultSet().getMessage(). I haven't tried it, but looking at the source code, it seems like this should work.
Looks like you can pass in a object with a success and fail methods. From the docs http://docs.sencha.com/touch/2-0/#!/api/Ext.data.Model-method-save
options : Object/Function
Options to pass to the proxy. Config object for Ext.data.Operation. If you pass a function, this will automatically become the callback method. For convenience the config object may also contain success and failure methods in addition to callback - they will all be invoked with the Model and Operation as arguments.
So you should be able to do:
var user = Ext.create('App.model.User', {name: "Bill"});
user.save({
success: function(){
},
failure: function(){
}
});
I don't know what is the callbacks, but usually what I do to find out:
success:function(a,b,c,d){
console.log(a,b,c,d);
}
and then look at the data in my console and rename the vars accordingly.
Hope this helps.
var user = Ext.create('App.model.User', {name: "Bill"});
user.save({
success : function(){
console.log('success', arguments);
},
failure : function(model, operation){
var reader = model.getProxy().getReader(),
message = reader.getMessage(reader.rawData)
console.log('failure message : ' + message);
}
});