【问题标题】:web API file downloading in chunks from SQL server从 SQL Server 分块下载 Web API 文件
【发布时间】:2018-08-30 13:53:42
【问题描述】:

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

我有两种方法

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

【问题讨论】:

    标签: asp.net-web-api chunks


    【解决方案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 header。 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/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-31
      • 1970-01-01
      • 1970-01-01
      • 2014-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多