我想从Chunks的Sqlserver下载文件,并使用我的Web API中的pushstreamcontent或streamcontent将其响应给我的客户端。实现此目的的正确方法是什么?
我脑中有两种方法
答案 0 :(得分:1)
我相信这应该可以帮助您解决问题:
public HttpResponseMessage Get([FromUri]string filename)
{
string path = HttpContext.Current.Server.MapPath("~/" + filename);
if (!File.Exists(path))
{
throw new HttpResponseException("The file does not exist.", HttpStatusCode.NotFound);
}
try
{
MemoryStream responseStream = new MemoryStream();
Stream fileStream = File.Open(path, FileMode.Open);
bool fullContent = true;
if (this.Request.Headers.Range != null)
{
fullContent = false;
// Currently we only support a single range.
RangeItemHeaderValue range = this.Request.Headers.Range.Ranges.First();
// From specified, so seek to the requested position.
if (range.From != null)
{
fileStream.Seek(range.From.Value, SeekOrigin.Begin);
// In this case, actually the complete file will be returned.
if (range.From == 0 && (range.To == null || range.To >= fileStream.Length))
{
fileStream.CopyTo(responseStream);
fullContent = true;
}
}
if (range.To != null)
{
// 10-20, return the range.
if (range.From != null)
{
long? rangeLength = range.To - range.From;
int length = (int)Math.Min(rangeLength.Value, fileStream.Length - range.From.Value);
byte[] buffer = new byte[length];
fileStream.Read(buffer, 0, length);
responseStream.Write(buffer, 0, length);
}
// -20, return the bytes from beginning to the specified value.
else
{
int length = (int)Math.Min(range.To.Value, fileStream.Length);
byte[] buffer = new byte[length];
fileStream.Read(buffer, 0, length);
responseStream.Write(buffer, 0, length);
}
}
// No Range.To
else
{
// 10-, return from the specified value to the end of file.
if (range.From != null)
{
if (range.From < fileStream.Length)
{
int length = (int)(fileStream.Length - range.From.Value);
byte[] buffer = new byte[length];
fileStream.Read(buffer, 0, length);
responseStream.Write(buffer, 0, length);
}
}
}
}
// No Range header. Return the complete file.
else
{
fileStream.CopyTo(responseStream);
}
fileStream.Close();
responseStream.Position = 0;
HttpResponseMessage response = new HttpResponseMessage();
response.StatusCode = fullContent ? HttpStatusCode.OK : HttpStatusCode.PartialContent;
response.Content = new StreamContent(responseStream);
return response;
}
catch (IOException)
{
throw new HttpResponseException("A generic error occured. Please try again later.", HttpStatusCode.InternalServerError);
}
}
请注意,在使用Web API时,您无需手动解析文本形式的Range标头。 Web API会自动为您解析它,并为每个范围提供一个From和To属性。 From和To的类型为Nullable,因为这些属性可以为null(认为bytes = -100和bytes = 300-)。这些特殊情况必须谨慎处理。
要考虑的另一种特殊情况是To大于资源大小。在这种情况下,它等效于To为null,在这种情况下,您需要从From开始返回到资源结尾。 如果返回完整的资源,通常状态码设置为200 OK。如果仅返回部分资源,通常状态码将设置为206 PartialContent。
此解决方案是本文的一部分,其中涵盖了许多其他内容,我建议您检查一下:https://blogs.msdn.microsoft.com/codefx/2012/02/23/more-about-rest-file-upload-download-service-with-asp-net-web-api-and-windows-phone-background-file-transfer/