Chciałbym użyć interfejsu IRequiresRequestStream
, aby umożliwić przesyłanie dużych plików (plików wideo) za pomocą ServiceStack (v3) i kodowane przesyłanie kodowania. Standardowy upload plików nie radzi sobie z niektórymi większymi plikami wideo, które przesyłają nasi klienci, dlatego staramy się włączyć kodowane kodowanie transferowe dla tych plików.C# Podzielone przesyłanie plików w połączeniu z dostępem do parametrów trasy w ServiceStack
Udało mi się przetestować przesyłanie zakodowanych plików z kodowaniem transferowym, ale istnieje szereg parametrów, które również muszą zostać przesłane z plikiem.
Od IRequiresRequestStream
pomija parser obiektów żądań ServiceStack, inne parametry w obiekcie żądania obok Stream
są oczywiście niewypełnione. Jako utwór wokół widzę następujące opcje:
- parametry string zapytanie, dostępny za pośrednictwem
this.Request.QueryString
kolekcji - parametrów niestandardowy nagłówek, dostępny za pośrednictwem
this.Request.Headers
kolekcji - Path, dostępny za pośrednictwem
RequestBinder
??
Udało mi się już wdrożyć opcje 1 i 2, ale w jakiś sposób nie czuję się wystarczająco WYDAWCZY. Wolałbym korzystać z Path -> RequestDTO
, ale mam problemy z RequestBinder
.
Usługa:
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);
}
Zapytanie:
[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; }
}
WebClient:
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();
}
Zgaduję prosty kierunek podjąć jest coś wzdłuż następujące linie, ale wydaje się, jak kundel.
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;
});
Zrobiłem trochę Googling dla przykładów RequestBinders
w tym scenariuszu. Jestem pewien, że muszą być wbudowane metody ServiceStack do analizowania Path
, ale ja z tym walczę. Czy ktoś ma przykład, który chcieliby udostępnić?