c#文件上传的分块传输,结合对ServiceStack中路由参数的访问
我希望使用c#文件上传的分块传输,结合对ServiceStack中路由参数的访问,c#,.net,
servicestack,chunked-encoding,C#,.net,
servicestack,Chunked Encoding,我希望使用IRequiresRequestStream接口使用ServiceStack(v3)和分块传输编码来实现大文件上传(视频文件)。标准的文件上传似乎无法处理我们的客户正在上传的一些较大的视频文件,因此我们希望为这些文件启用分块传输编码 我已经成功地测试了分块传输编码的文件上传,但是还有一些参数也需要随文件一起发送 由于IRequiresRequestStream绕过ServiceStack请求对象解析器,请求对象中与流相邻的任何其他参数显然都不会被填充。作为解决方案,我可以看到以下选项:
IRequiresRequestStream
接口使用ServiceStack(v3)和分块传输编码来实现大文件上传(视频文件)。标准的文件上传似乎无法处理我们的客户正在上传的一些较大的视频文件,因此我们希望为这些文件启用分块传输编码
我已经成功地测试了分块传输编码的文件上传,但是还有一些参数也需要随文件一起发送
由于IRequiresRequestStream
绕过ServiceStack请求对象解析器,请求对象中与流
相邻的任何其他参数显然都不会被填充。作为解决方案,我可以看到以下选项:
this.Request.QueryString
集合访问this.Request.Headers
集合访问RequestBinder
访问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; }
}
网络客户:
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();
}
使用WebClient发送私有静态异步任务(字节[]文件、字符串哈希、customerId)
{
var client=(HttpWebRequest)WebRequest.Create(string.Format(“http://localhost.fiddler:58224/upload/{0}/{1}(customerId,hash));
client.Method=WebRequestMethods.Http.Post;
添加(“Cookie”,“ss pid=XXXXXXXXXX;ss id=YYYYYY”);
//以下4行启用流式处理
client.AllowWriteStreamBuffering=false;
client.SendChunked=true;
client.ContentType=“application/json”;
client.Timeout=int.MaxValue;
使用(var fileStream=newmemorystream(文件))
{
Copy(client.GetRequestStream());
}
返回新的StreamReader(client.GetResponse().GetResponseStream()).ReadToEnd();
}
我猜简单的方向是沿着下面的路线,但这似乎是一个混乱
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.Add(typeof(AttachmentStreamRequest),httpReq=>{
var dto=新的AttachmentStreamRequest();
var segments=base.Request.PathInfo.Split(新[]{'/'},StringSplitOptions.RemoveEmptyEntries);
dto.CustomerId=段[1].As();
dto.Hash=segments[2].As();
//流复制到dto.RequestStream和其他参数等。。。。
返回dto;
});
在这个场景中,我用谷歌搜索了一下
RequestBinders
的例子。我确信必须有内置的ServiceStack方法来解析路径
,但我正在努力解决这个问题。有人想分享一个例子吗?最近我还研究了使用自定义标题的分块传输。不幸的是,我发现它在HttpWebRequest类和.NET Framework中都不受开箱即用的支持。唯一对我有效的解决方案是通过TCP实现分块传输HTTP通信。它不像行乞时听起来那么复杂。您只需要打开TCP客户端连接,根据需要格式化头,将流分块并发送
以下是分块传输协议的定义: