我期待使用IRequiresRequestStream
接口來啓用使用ServiceStack(v3)和分塊傳輸編碼的大文件上傳(視頻文件)。標準文件上傳似乎無法應付我們客戶上傳的一些較大的視頻文件,因此我們希望爲這些文件啓用分塊傳輸編碼。c#文件上傳的塊傳輸結合訪問ServiceStack中的路由參數
我已經成功測試了分塊傳輸編碼文件上傳,但還有一些參數也需要通過文件發送。
由於IRequiresRequestStream
繞過ServiceStack請求對象解析器,請求對象旁邊的任何其他參數顯然不會填充。通過RequestBinder
通過this.Request.Headers
收集
- 查詢字符串參數,通過
this.Request.QueryString
收集 - 自定義頭參數訪問,訪問,訪問??:作爲一個工作圍繞我可以看到下面的選項
我已經設法實現選項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
,但我很苦惱。有沒有人有他們想分享的例子?