2

目前正在研究使用 signalR 在处理文件时向用户呈现文件的进度报告。我正在使用 asp.net MVC 4。通过 Ajax 进行发布/获取时,我可以毫无问题地获取状态更改。

因为我需要上传一个文件(没有 ajax,因为 1:我不能要求用户启用 js 才能提交文件;2:我不相信除了 HTML5 之外,它很容易完成这样的任务) .

编辑: 当我说我不能要求用户拥有 JS 时,我的意思是提交文件不能依赖 JS,因为这是核心功能。但是,我希望那些启用了 JS 的人能够看到处理/导入另一个程序的进度。我目前不关心/关心实际的文件传输进度,但更重要的是将状态消息发送回程序中导入的当前状态。

在我调用表单 Post 之后,为了实现在文件处理过程中更新进度的目标,建议采用什么方法?笔记:

示例代码:

$(function () {
    var fileUploadHub = $.connection.fileUploadHub;

    fileUploadHub.updateProgress = function (value) {
        updateProgressBar(value);
    };

    fileUploadHub.updateStatusText = function (text) {
        alert("you got to updateStatus");
        updateText(text);
    };
    $.connection.hub.logging = true;
    $.connection.hub.start();
});

function updateProgressBar(value) {
    $("#progressbar").progressbar({ value: value });
}

function updateText(text) {
    $("#statusText").append("<li>" + text + "</li>");
}

//Form : 由模型支持

@using (Html.BeginForm( "UploadFile", "FileUpload", FormMethod.Post,
    new { enctype = "multipart/form-data"}))
{
    <input type="file" id="Files" name="Files" accept="text/xml" />
    <br />
    <input type="submit" id="submitButton" value="Submit" />
}

控制器:

public ActionResult SubmitFile(MyModel model)
{
  ...
  ProcessFile(model.file)
  ...
}

public void ProcessFile(File file)
{
  var myHub = GlobalHost.ConnectionManager.GetHubContext<FileUploadHub>();
  myHub.Clients.updateStatusText("testz");
}

集线器类:

public class FileUploadHub : Hub
{
}
4

1 回答 1

6

您还需要做的是使用 POST 发回用户的 SignalR ConnectionId。然后,当帖子开始时,您需要获取 HubContext,并且在整个 POST 逻辑中,您可以通过该 ConnectionId 将通知发送回特定客户端。

  1. 将输入 type="hidden" 添加到您的表单中。

    <input type="hidden" id="mySignalRConnectionIdHidden" name="SignalRConnectionId" />
    
  2. 假设 JavaScript 已启用并且您连接到集线器,请将隐藏输入的值设置为 start() 回调中 SignalR 的 connectionid 值。

    $.connection.hub.start().done(function ()
    {
        $("#mySignalRConnectionIdHidden").val($.connection.connectionId);
    });
    
  3. POST 到服务器端的第一步是为您的 Hub 获取 HubContext 并获取您要与之对话的客户端。

    // Get the value of the hidden from the request
    string currentClientConnectionId = Request.Form["SignalRConnectionId"];
    
    // Get the hub context
    IHubContext myHubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
    
    // Resolve a the client that corresponds to the current request
    dynamic currentClient = myHubContext.Client(currentClientConnectionId);
    
  4. 在整个 POST 处理逻辑的各个点,您现在可以将消息发送回启动上传的客户端:

    ... do some stuff ...
    
    currentClient.stepOneCompleted();
    
    .... do some more stuff ...
    
    currentClient.stepTwoCompleted();
    
    ... etc ...
    

显然,在第 4 步中,您还可以将数据作为参数传递回客户端,我只是在这里不显示。

最后,对于没有启用 JS 或由于某种原因无法连接的客户端,您可以在 POST 上检测到表单值为空,然后您就知道没有建立 SignalR 连接。然后,您可以设置 currentClient = null 并在您将调用客户端回调并完全跳过回调的地方检测到这一点。

于 2012-10-08T18:43:17.430 回答