c#文件上传的块传输结合访问ServiceStack中的路由参数

问题描述:

我期待使用IRequiresRequestStream接口来启用使用ServiceStack(v3)和分块传输编码的大文件上传(视频文件)。标准文件上传似乎无法应付我们客户上传的一些较大的视频文件,因此我们希望为这些文件启用分块传输编码。c#文件上传的块传输结合访问ServiceStack中的路由参数

我已经成功测试了分块传输编码文件上传,但还有一些参数也需要通过文件发送。

由于IRequiresRequestStream绕过ServiceStack请求对象解析器,请求对象旁边的任何其他参数显然不会填充。通过RequestBinder通过this.Request.Headers收集

  • 路径

    1. 查询字符串参数,通过this.Request.QueryString收集
    2. 自定义头参数访问,访问,访问??:作为一个工作围绕我可以看到下面的选项

    我已经设法实现选项1和2,但不知何故都不觉得RESTful足够。我宁愿使用Path -> RequestDTO,但我正在努力与RequestBinder

    服务:

    public object Any(AttachmentStreamRequest request) 
    { 
        byte[] fileBytes = null; 
    
        using (var stream = new MemoryStream()) 
        { 
         request.RequestStream.WriteTo(stream); 
         length = stream.Length; 
         fileBytes = stream.ToArray(); 
        } 
    
        string filePath = @"D:\temp\test.dat"; 
        File.WriteAllBytes(filePath, fileBytes); 
    
        var hash = CalculateMd5(filePath); 
        var requestHash = this.Request.QueryString["Hash"]; 
        var customerId = this.Request.QueryString["CustomerId"]; 
        var fileName = this.Request.QueryString["FileName"]; 
    
        // nicer would be 
        // var requestHash = request.Hash; 
        // var customerId = request.CustomerId; 
    
        // save file.... 
    
        // return response 
        return requestHash == hash 
           ? new HttpResult("File Valid", HttpStatusCode.OK) 
           : new HttpResult("Invalid Hash", HttpStatusCode.NotAcceptable); 
    } 
    

    请求:

    [Route("/upload/{CustomerId}/{Hash}", "POST", Summary = @"POST Upload attachments for a customer", Notes = "Upload customer attachments")] 
    public class AttachmentStreamRequest : IRequiresRequestStream 
    { 
        // body 
        public Stream RequestStream { get; set; } 
    
        // path  
        public int CustomerId { get; set; } 
    
        // query 
        public string FileName { get; set; } 
    
        // query 
        public string Comment { get; set; } 
    
        // query 
        public Guid? ExternalId { get; set; } 
    
        // path 
        public string Hash { get; set; } 
    } 
    

    Web客户端:

    private static async Task<string> SendUsingWebClient(byte[] file, string hash, customerId) 
    { 
        var client = (HttpWebRequest)WebRequest.Create(string.Format("http://localhost.fiddler:58224/upload/{0}/{1}", customerId, hash)); 
        client.Method = WebRequestMethods.Http.Post; 
        client.Headers.Add("Cookie", "ss-pid=XXXXXXXXXXX; ss-id=YYYYYYYYYY"); 
    
        // the following 4 rows enable streaming 
        client.AllowWriteStreamBuffering = false; 
        client.SendChunked = true; 
        client.ContentType = "application/json"; 
        client.Timeout = int.MaxValue; 
    
        using (var fileStream = new MemoryStream(file)) 
        { 
         fileStream.Copy(client.GetRequestStream()); 
        } 
    
        return new StreamReader(client.GetResponse().GetResponseStream()).ReadToEnd(); 
    } 
    

    我猜简单的方向走是大意如下的东西,但它似乎像一个kludge。

    RequestBinders.Add(typeof(AttachmentStreamRequest), httpReq => { 
        var dto = new AttachmentStreamRequest(); 
        var segments = base.Request.PathInfo.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); 
    
        dto.CustomerId = segments[1].As<int32>(); 
        dto.Hash = segments[2].As<string>(); 
    
        // Stream copy to dto.RequestStream and other params etc.... 
    
        return dto; 
    }); 
    

    我已经做了一些谷歌搜索在这种情况下的RequestBinders例子。我确定必须有内置的ServiceStack方法来解析Path,但我很苦恼。有没有人有他们想分享的例子?

  • 最近我还调查了使用块化传输与自定义标题。不幸的是,我发现它并不支持HttpWebRequest类,也不支持.NET框架。对我而言唯一的解决方案是通过TCP实现分块传输HTTP通信。它并不像起步时那样复杂。您只需打开TCP客户端连接,根据需要格式化标题,按块分割流并发送它。

    这里是分块传输协议的定义:

    https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding