Readstatechange在jQuery XMLHttpRequest中过早地触发MVC5 Action

时间:2017-08-04 00:34:03

标签: jquery asp.net-mvc asp.net-mvc-5

我有一个jQuery函数来上传图片:

        $("#addPictureForm").submit(function() {
            var xhr = new XMLHttpRequest();
            var fd = new FormData();
            fd.append("file", $('#fileSelect')[0].files[0]);
            var id = @Model.myId;
            fd.append("id", id);
            var token = $('#__AjaxAntiForgeryForm input[name="__RequestVerificationToken"]').val();
            fd.append("__RequestVerificationToken", token);

            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    alert(xhr.responseText); // this never fires...
                }
            }
            xhr.open("POST", "/Images/AddPicture/", true);
            xhr.send(fd);
        });

由此操作符处理:

    [ValidateAntiForgeryToken]
    public string AddPicture(HttpPostedFileBase file, int id)
    {
        if (file == null)
            throw new Exception("File name must be selected.");

        var buffer = new byte[file.ContentLength];

        ... store image, get guid for it ...

        // return a uri that can be plugged into the img tag
        return Url.HttpRouteUrl("Default", new {controller = "Images", action = "GetImage", id = Id, picGuid = pictureGuid});
    }

如果只检查readystate == 4而不是等待响应,则在调用此函数后立即触发onreadystatechange事件。如果我添加200的状态,那么它永远不会触发。该功能用于存储图像,如果我刷新页面,我会看到它出现。我怎样才能从这个动作中得到答案?

1 个答案:

答案 0 :(得分:0)

由于操作是提交,因此会发布呼叫并重新加载页面。我甚至没有看到开发者窗口。

Controller返回一个字符串也有问题。在我使用返回Json(...)方法之前,我没有成功地将uri放到我需要的图片上。

一旦我删除了添加图片按钮周围的表单元素并使其纯粹成为按钮点击处理程序而不是提交事件,它就会在同一页面上完成并调用成功事件。

我不想强迫用户点击额外的时间来执行上传,所以我也将上传放在文件输入元素的change事件中。

以下是我最终的结果:

HTML:

    <div class="col-md-10"> 
        <fieldset>
            Add Picture: <input type="file" id="fileSelect" />
        </fieldset>
    </div>

jQuery的:

// AddPicture - Trigger when file selected
$("#fileSelect").change(function(e) {
    // Create FormData object
    var fd = new FormData();
    fd.append("file", $('#fileSelect')[0].files[0]);
    var id = @Model.Id;
    fd.append("id", id);
    var token = $('#__AjaxAntiForgeryForm input[name="__RequestVerificationToken"]').val();
    fd.append("__RequestVerificationToken", token);

    $.ajax({
        url: '/Images/AddPicture/',
        type: "POST",
        contentType: false, // Not to set any content header
        processData: false, // Not to process data
        data: fd,
        success: function(result) {
            alert("picture loaded successfully - do something here");
        },
        error: function(err) {
            alert(err.statusText);
        }
    });
});

控制器:

    [ValidateAntiForgeryToken]
    [HttpPost]
    public ActionResult AddPicture(HttpPostedFileBase file, int id)
    {
        if (file == null)
            throw new Exception("File name must be selected.");

        var buffer = new byte[file.ContentLength];

        file.InputStream.Read(buffer, 0, file.ContentLength);

        var returnString = StorePicAndCreateReferenceGuid(buffer);

        return Json(Url.HttpRouteUrl("Default", 
            new {controller = "Images", action = "GetImage", 
            id = Id, picGuid = pictureGuid}));
    }

在我的代码中,我可以使用我返回的引用在页面上就地加载上传的图片。

我可能会很好地坚持使用XMLHttpRequest,但是已经切换到ajax调用,所以我坚持使用它。