[英]c# Chunked transfer of file upload in combination with access to route parameters in ServiceStack
我希望使用IRequiresRequestStream
接口來啟用使用 ServiceStack (v3) 和分塊傳輸編碼的大文件上傳(視頻文件)。 標准文件上傳似乎無法處理我們客戶上傳的一些較大的視頻文件,因此我們希望為這些文件啟用分塊傳輸編碼。
我已經成功測試了分塊傳輸編碼文件上傳,但是還有許多參數需要與文件一起發送。
由於IRequiresRequestStream
繞過了 ServiceStack 請求對象解析器,因此請求對象中與Stream
一起的任何其他參數顯然不會被填充。 作為解決方法,我可以看到以下選項:
this.Request.QueryString
集合訪問this.Request.Headers
集合訪問RequestBinder
訪問? 我已經設法實現了選項 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; }
}
網絡客戶端:
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();
}
我猜想采取的簡單方向是以下幾行,但這似乎是一團糟。
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 Framework 中都不支持開箱即用。 唯一對我有用的解決方案是通過 TCP 實現分塊傳輸 HTTP 通信。 它並不像開始時聽起來那么復雜。 您只需要打開 TCP 客戶端連接,根據需要格式化標頭,按塊拆分流並發送。
以下是分塊傳輸協議的定義:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.