1

我有一个这样的剑道上传控件:

@(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))
)

在控制器中,它的 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 分配了变量。

上传按预期工作,Success 事件也按预期工作。(警报只是为了测试。)

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方法返回的内容?

4

2 回答 2

0

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

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

事件的实际顺序是:

js onUpload > Controller.UploadAsync() > js onSuccess

js onRemoveFile > Controller.RemoveAsync > js onSuccess

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

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

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

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 分配是因为这个线程,它具有以下信息:

解决方案:为上传事件定义一个函数并修改“数据”有效负载所需的一切。

添加上传JS功能以添加参数“codeID”在我的情况下。

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

现在在控制器上添加参数,就是这样。

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

我的不是在 Upload 事件中,而是在 Remove 事件中。

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

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

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

    return Json(new { ImageName = returnName }, "text/plain");
}
于 2017-09-25T17:07:29.560 回答
0

看起来remove事件没有提供这种数据,所以我只看到了解决这个问题的解决方法。

您可以尝试将结果名称放在标题中,您应该能够读取结果:

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

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

我还没有对此进行测试,并且我发现remove事件并没有真正读取异步响应的风险,这可以解释为什么该response对象不可用。

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

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

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

于 2017-09-25T15:59:19.130 回答