Kendo上传控件移除事件无响应

Kendo Upload control remove event has no response

我有一个像这样的 kendo 上传控件:

@(Html.Kendo().Upload()
    .Name("attachments")
    .Async(a => a
        .Save("UploadAsync", "Intel")
        .Remove("RemoveAsync", "Intel")
        .AutoUpload(true)
    )
    .Events(e => e
        .Success("onSuccessfulUpload")
        .Remove("onRemoveFile")
    )
    .Validation(v => v.AllowedExtensions(exts))
)

在controller中,它的Save方法是这样的:

public ActionResult UploadAsync(IEnumerable<HttpPostedFileBase> attachments)
{
    string filename;
    // ... do things ...
    return Json(new { ImageName = filename }, "text/plain");
}

其中变量 filename 被赋值。

它在控制器中的 Remove 方法看起来非常相似:

public ActionResult RemoveAsync(string[] fileNames)
{
    string filename;
    // ... do things ...
    return Json(new { ImageName = filename }, "text/plain");
}

我验证了两种控制器方法 都被正确调用 并且变量 filename 赋值给这两种情况。

上传按预期进行,成功事件也按预期进行。 (警报仅用于测试。)

function onSuccessfulUpload(e) {
    alert(e.response.ImageName);
}

问题出现在删除文件时。

当我到达 Remove 事件时,e 没有 .response。它有 e.filese.sender,但没有响应。

function onRemoveFile(e) {
    alert(e.response);                    // undefined!
    alert(JSON.stringify(e.files));       // works, but does not have what I need
}

如何访问 RemoveAsync 方法 returns?

remove 事件似乎没有提供此类数据,所以我只看到解决此问题的解决方法。

您可以尝试将结果名称输入 headers,您应该可以读取结果:

// Controller
Response.AddHeader("ImageName", imageName); // before Json(...)

// View/JS
alert(e.headers['ImageName']);

我还没有测试过,我发现 remove 事件没有真正读取异步响应的风险,这可以解释为什么 response object 是不可用。

在这种情况下,您可以尝试使用以下解决方法:不要在删除时调用任何 Url(或使用一些没有任何 body 的操作,只是一个简单的结果)和内部事件回调,自己执行RemoveAsync

// View/JS
function onRemoveFile(e) {
    $.post('@Html.Url("RemoveAsync", "Intel")', e.files, function(response) {
        alert(response);
    });
}

它不是很漂亮,但它应该可以工作并提供您需要的结果。

经过一段时间的摸索,我找到了答案。

关键在于事件的顺序。我的第一个假设是 Success 事件在成功上传后调用,Remove 事件在成功(?)删除后调用。

事件的实际顺序是:

js onUpload > Controller.UploadAsync() > js onSuccess

js onRemoveFile > Controller.RemoveAsync > js onSuccess

我在 javascript 中创建了两个并行数组来表示在客户端上传的文件 e.files,其中包含每个文件的 uid,以及服务器端控制器方法创建的文件名(重命名文件)。

var fileUids = [];
var fileSaveNames = [];

当我发现有一个 e.operation 指定成功的操作时,我将 onSuccessfulUpload 函数更改为此:

function onSuccess(e) {
    if (e.operation == "upload") {
        var filename = e.response.ImageName;
        var uid = e.files[0].uid;

        fileUids.push(uid);
        fileSaveNames.push(filename)
        // ...
    }
    else if (e.operation == "remove") {
        var uid = e.files[0].uid;
        var saveIdx = fileUids.indexOf(uid);

        fileSaveNames.splice(saveIdx, 1);
        fileUids.splice(saveIdx, 1);
        // ...
    }
}

然后我更新了 removeFile 函数,我现在知道它在 控制器中的方法之前 被调用。

function removeFile(e) {

    var uid = e.files[0].uid;
    var idx = fileUids.indexOf(uid);
    e.data = { fileToRemove: fileSaveNames[idx] };
}

e.data 分配是因为 this thread,它具有以下信息:

Solution: All that's needed it to define a function for the upload event and modify the "data" payload.

Add the upload JS function to add a parameter "codeID" in my case.

$("#files").kendoUpload({
    [...]
    upload: function (e) {
        e.data = { codeID: $("#id").val() };
    }
});

Now on the controller add the parameter and that's it.

[HttpPost]
public ActionResult Save(IEnumerable<HttpPostedFileBase> files, Guid codeID) { }

我的不是在上传事件中,而是在删除事件中。

我选择了参数名称fileToRemove,控制器中新的RemoveAsync方法是这样的:

public ActionResult RemoveAsync(string[] fileNames, string fileToRemove)
{
    string returnName = "";

    if (!string.IsNullOrWhiteSpace(fileToRemove))
    {
        // ... do things ...
    }

    return Json(new { ImageName = returnName }, "text/plain");
}