抓住太长的表单提交

我正在开发一个HTML页面,它具有简单的HTML表单(没有特别的)被按钮提交。 有几种情况表单提交和响应时间太长(如果每次真的回来)。 如何在等待响应时间过长时触发某些回调的方式来组织表单? 我们可能会显示一些用户通知,表明我们的服务器在这种情况下超载。

这是通过表单发送的请求:

POST http://example.com/search HTTP/1.1
Host: example.com
Proxy-Connection: keep-alive
Content-Length: 83
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://example.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://example.com/
Accept-Encoding: gzip, deflate
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: [cookie definition omitted]

[form data omitted]

Proxy-Connection: keep-alive以某种方式影响进程? 谷歌搜索引导我到https://github.com/caxap/jquery-safeform插件,但它有一个不同的目的。


这取决于您想向用户展示哪种类型的用户界面。 您可以简单地降低服务器级别的超时时间,如果无法及时完成响应,则会中止。 但是,用户体验相当苛刻,因为他们只会得到一个通用的超时错误,甚至可能不会从您的网站发出。 (他们必须点击返回或返回您的网站。)

如果您只想在经过一定时间后显示消息,则可以附加到表单的提交事件,并使用setTimeout显示警报或其他内容:

$('#MyForm').on('submit', function () {
    setTimeout(30000, function () { // number is milliseconds
        alert('Sorry this is taking so long.');
    });
});

最后,如果有一些跟踪服务器端完成的动作进度的方法,则可以使用诸如Web套接字或通过AJAX进行长轮询的方法来提供某种进度条或状态更新。 不过,这有点复杂,需要您进行一些研究。


有两种方法,我会写两个单独的答案。

XMLHttpRequest进度方法 (适用于现代浏览器)

只需发送数据并阅读从XMLHttpRequest上传进度:

//-------------upload ------------------


var lastProgressIndex = -1;


//is the file api available in this browser
//only override *if* available.
if (new XMLHttpRequest().upload) {
    $("#upload-files").click(function () {       
        upload_files($("#files-to-upload")[0].files, lastProgressIndex++);
        return false;
    });
    $("#files-to-upload").change(function () {
        upload_files($("#files-to-upload")[0].files, lastProgressIndex++);
        return false;
    });
    $("#upload-files").hide();
}
function resetFormElement(elem) {
    elem.wrap('<form>').closest('form').get(0).reset();
    elem.unwrap();
}

function clear_upload() {
    //https://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery
    var upload = $("#files-to-upload");
    //upload.replaceWith(upload = upload.clone(true));
    resetFormElement(upload);
}

//accepts the input.files parameter
function upload_files(filelist) {
    if (typeof filelist !== "undefined") {
        for (var i = 0, l = filelist.length; i < l; i++) {
            upload_file(filelist[i], lastProgressIndex++);
        }
    }
    clear_upload();
}

//each file upload produces a unique POST
function upload_file(file, index) {

    //TODO - vytvor progress bar podle indexu
    $("#progresscontainer").append('<div id="progressbar' + index + '" class="progressbar"><div id="progresslabel' + index + '" class="progressbarlabel"></div></div>')

    var progressBarSelector = "#progressbar" + index;
    var progressLabelSelector = "#progresslabel" + index;
    var fileName = file.name;

    var xhr = new XMLHttpRequest();

    xhr.upload.addEventListener("progress", function (evt) {
        if (evt.lengthComputable) {
            //update the progress bar

            var percent = Math.floor((evt.loaded / evt.total) * 100) + "%";

            //TODO http://www.binaryintellect.net/articles/859d32c8-945d-4e5d-8c89-775388598f62.aspx                  

            $(progressBarSelector).css({
                width: percent
            });
            $(progressLabelSelector).html(fileName + ' ' + percent);
        }
    }, false);

    // File uploaded
    xhr.addEventListener("load", function () {
        $(progressLabelSelector).html(fileName + " uploaded");

        AddImageToGallery(GetFilenameWithoutExt(fileName));

        $(progressBarSelector).fadeOut(500, function () {
            $(progressBarSelector).remove();
        });
    }, false);

    var guid = $("#Identification").val();
    xhr.open("post", "/uploadurl/uploadfile/" + guid, true);

    // Set appropriate headers
    // We're going to use these in the UploadFile method
    // To determine what is being uploaded.
    xhr.setRequestHeader("Content-Type", "multipart/form-data");
    xhr.setRequestHeader("X-File-Name", file.name);
    xhr.setRequestHeader("X-File-Size", file.size);
    xhr.setRequestHeader("X-File-Type", file.type);

    // Send the file
    xhr.send(file);
}

和服务器部分:

private UploadedFile[] RetrieveFileFromRequest()
{
    List<UploadedFile> uploadedFiles = new List<UploadedFile>();


    if (Request.Files.Count > 0)
    { //they're uploading the old way

        for (int i = 0; i < Request.Files.Count; i++)
        {
            var file = Request.Files[0];
            string contentType = file.ContentType;
            string filename = file.FileName;

            UploadedFile uploadedFile = SaveUploadedFile(file.InputStream, file.ContentLength, filename, contentType);

            uploadedFiles.Add(uploadedFile);
        }
    }
    else if (Request.ContentLength > 0)
    {
        string filename = Request.Headers["X-File-Name"];
        string contentType = Request.Headers["X-File-Type"];

        UploadedFile uploadedFile = SaveUploadedFile(Request.InputStream, Request.ContentLength, filename, contentType);
        uploadedFiles.Add(uploadedFile);
    }

    return uploadedFiles.ToArray();
}

这些来源是对原始文章的修改。 有相关的stackoverflow问题。


如何在等待响应时间过长时按照触发某种回调的方式来组织表单?

这是基于你的算法。 你可以像蛮力计算一样估计时间,并在开始执行之前显示结果。 如果您开始处理并且在花费太多时间后再打破它,这不是一个优化的解决方案!

更新 :如果你不能像上面那样估计,至少要编写一个asynch控制器方法,当一个动作必须执行多个独立的长时间运行操作时,这个方法非常有用。 遵循这个:

  • 用不显眼的Ajax写一个Ajax表单
  • OnBegin表单选项定义一个函数来调用定时器
  • 计时器的超时事件将向用户显示另一件事。
  • 编写一个asynch控制器方法的操作,其中包含一个定时器停止处理,当它需要超过?? 秒。
  • 链接地址: http://www.djcxy.com/p/42085.html

    上一篇: Catch too long form submission

    下一篇: Why is my query string so long?