并行文件上传XMLHttpRequest请求以及为什么它们不起作用 [英] Parallel file upload XMLHttpRequest requests and why they won't work

查看:111
本文介绍了并行文件上传XMLHttpRequest请求以及为什么它们不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用XMLHttpRequest并行上传许多文件(目前为3个).如果有一些代码可以将它们从许多已删除文件的列表中拉出,并确保每次发送3个文件(如果有).

I am trying to upload many (3 for now) files in parallel using XMLHttpRequest. If have some code that pulls them from a list of many dropped files and makes sure that at each moment I am sending 3 files (if available).

这是我的代码,据我所知这是标准代码:

Here is my code, which is standard as far as I know:

            var xhr = item._xhr = new XMLHttpRequest();
            var form = new FormData();
            var that = this;

            angular.forEach(item.formData, function(obj) {
                angular.forEach(obj, function(value, key) {
                    form.append(key, value);
                });
            });

            form.append(item.alias, item._file, item.file.name);

            xhr.upload.onprogress = function(event) {
                // ...
            };

            xhr.onload = function() {
                // ...
            };

            xhr.onerror = function() {
                // ...
            };

            xhr.onabort = function() {
                // ...
            };

            xhr.open(item.method, item.url, true);

            xhr.withCredentials = item.withCredentials;

            angular.forEach(item.headers, function(value, name) {
                xhr.setRequestHeader(name, value);
            });

            xhr.send(form);

看一下Opera开发人员工具中的网络监视器,我发现这种方法行之有效,而且我始终可以得到3个正在进行的文件:

Looking at the network monitor in Opera's developer tools, I see that this kinda works and I get 3 files "in progress" at all times:

但是,如果我看一下请求的处理方式,我发现3个上载中的2个(这里是看似长时间运行的)处于待处理"状态,而3个请求中只有1个是真正的一次活跃.这也反映在上载时间上,因为这种并行性似乎没有时间上的改善.

However, if I look the way the requests are progressing, I see that 2 of the 3 uploads (here, the seemingly long-running ones) are being put in status "Pending" and only 1 of the 3 requests is truly active at a time. This gets reflected in the upload times as well, since no time improvement appears to happen due to this parallelism.

我已经在所有代码中放置了控制台日志,看来这与我的代码无关.

I have placed console logs all over my code and it seems like this is not a problem with my code.

我应该了解关于并行上传文件的浏览器限制吗?据我所知,AJAX的限制比我在这里使用的限制要高得多...向请求中添加文件会改变一切吗?

Are there any browser limitations to uploading files in parallel that I should know about? As far as I know, the AJAX limitations are quite higher in number of requests than what I use here... Is adding a file to the request changing things?

推荐答案

事实证明这是ASP.NET引起的问题. 来自同一SessionId的多个请求被序列化,因为它们锁定了会话对象.

This turned out to be ASP.NET causing the issue. Multiple requests coming from the same SessionId get serialized, because they lock the session object.

请参见此处.

我的解决方法是使此特定操作的会话为只读.这样,无需锁定. 这是我的代码(原始代码取自此处):

My fix was to make the session read-only for this particular action. That way, no locking was required. This is my code (original code taken from here):

public class CustomControllerFactory : DefaultControllerFactory
{
    protected override SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
        {
            return SessionStateBehavior.Default;
        }

        var actionName = requestContext.RouteData.Values["action"].ToString();
        MethodInfo actionMethodInfo;
        var methods = controllerType.GetMethods(BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
        actionMethodInfo = methods.FirstOrDefault(x => x.Name == actionName && x.GetCustomAttribute<ActionSessionStateAttribute>() != null);
        if (actionMethodInfo != null)
        {
            var actionSessionStateAttr = actionMethodInfo.GetCustomAttributes(typeof(ActionSessionStateAttribute), false)
                .OfType<ActionSessionStateAttribute>()
                .FirstOrDefault();

            if (actionSessionStateAttr != null)
            {
                return actionSessionStateAttr.Behavior;
            }
        }
        return base.GetControllerSessionBehavior(requestContext, controllerType);
    }
}


[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class ActionSessionStateAttribute : Attribute
{
    public SessionStateBehavior Behavior { get; private set; }
    public ActionSessionStateAttribute(SessionStateBehavior behavior)
    {
        this.Behavior = behavior;
    }
}

// In your Global.asax.cs
protected void Application_Start(object sender, EventArgs e)
{
    // .........
    ControllerBuilder.Current.SetControllerFactory(typeof(CustomControllerFactory));
}


// You use it on the controller action like that:
[HttpPost]
[Authorize(Roles = "Administrators")]
[ValidateAntiForgeryToken]
[ActionSessionState(SessionStateBehavior.ReadOnly)]
public async Task<ActionResult> AngularUpload(HttpPostedFileBase file){}

这是光荣的结果:

这篇关于并行文件上传XMLHttpRequest请求以及为什么它们不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆