从SQL Server分块下载Web API文件

时间:2018-08-30 13:53:43

标签: asp.net-web-api chunks

我想从Chunks的Sqlserver下载文件,并使用我的Web API中的pushstreamcontent或streamcontent将其响应给我的客户端。实现此目的的正确方法是什么?

我脑中有两种方法

  1. 多次调用:从客户端调用WEb API并在首次调用时获取文件元数据。传递Chunksize和Contentstart参数并下载块。
  2. 单次调用:在服务器端的Tempfolder中下载文件,并在单次调用中将流内容推送到客户端。

1 个答案:

答案 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/