• 使数据库大字段的 Server Side ASP.Net Web/Http 下载,支持 FlashGet (Client) 断点续传多线程下载


    今天看了 bestcomy 的
    例程:ASP.NET实现从MSSQL中分块断点续传下载image字段内容
    http://www.cnblogs.com/bestcomy/archive/2005/05/08/150815.html

    不过代码复杂了些!

    这里请大家参阅:
    ms-help://MS.NETFrameworkSDKv1.1.CHS/cpref/html/frlrfSystemDataCommandBehaviorClassTopic.htm
    注意:
    SequentialAccess
     提供一种方法,以便 DataReader 处理包含带有大二进制值的列的行。SequentialAccess 不是加载整行,而是使 DataReader 将数据作为流来加载。然后可以使用 GetBytes 或 GetChars 方法来指定开始读取操作的字节位置以及正在返回的数据的有限的缓冲区大小。
    当指定 SequentialAccess 时,尽管无需读取每个列,但是需要按照列的返回顺序读取它们。一旦已经读过返回的数据流中某个位置的内容,就不能再从 DataReader 中读取该位置或该位置之前的数据。当使用 OleDbDataReader 时,可重新读取当前列的值,直到读过它。当使用 SqlDataReader 时,一次只能读取一个列值。

    关于如何支持 FlashGet 断点续传多线程下载请参阅:
     http://blog.csdn.net/playyuer/archive/2004/08/02/58281.aspx
     http://blog.csdn.net/playyuer/archive/2004/08/02/58430.aspx

    因此代码可以更简单些,支持 Oracle 也不会太难:
    1. BlobDownload.aspx 前代码(HTML)

    <%@ Page language="c#" Codebehind="BlobDownload.aspx.cs" AutoEventWireup="false" Inherits="BlobDownload" %>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
    <HTML>
        
    <HEAD>
            
    <title>WebForm1</title>
            
    <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
            
    <meta name="CODE_LANGUAGE" Content="C#">
            
    <meta name="vs_defaultClientScript" content="JavaScript">
            
    <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
        
    </HEAD>
        
    <body MS_POSITIONING="GridLayout">
            
    <form id="Form1" method="post" runat="server">
            
    </form>
        
    </body>
    </HTML>


    2. BlobDownload.aspx 后代码 BlobDownload.aspx.cs

    using System;
    using System.Data;
    using System.Data.SqlClient;

    //namespace Microshaoft
    //{
        /// <summary>
        
    /// WebForm1 的摘要说明。
        
    /// </summary>

        public class BlobDownload : System.Web.UI.Page
        
    {
            
    private void Page_Load(object sender, System.EventArgs e)
            
    {
                
    //Sql*** 以后换成 Oracle*** 估计就可以实现支持 Oracle 了
                SqlConnection scn = new SqlConnection(@"Data Source=SERVER\PSQLKE;Initial Catalog=northwind;user id=sa");
                
    //字段顺序不要错
                SqlCommand scmd = new SqlCommand("SELECT categoryName,DataLength(Picture),Picture FROM Categories where categoryName='Test'", scn);
                scn.Open();
                SqlDataReader sdr 
    = scmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult);
                
    if (sdr.Read()) //只读取一条记录
                {
                    
    try
                    
    {
                        
    string FileName = sdr.GetString(0);//FileName
                        Response.AddHeader("Content-Disposition""attachment; filename=" + FileName + ".rar");

                        
    int size = 64 * 1024//buffer size
                        byte[] bytes = new byte[size];

                        
    long l = sdr.GetInt32(1);//DataLength
                        long p = 0;
                        Response.AddHeader(
    "Accept-Ranges""bytes");
                        
    if (Request.Headers["Range"!= null)
                        
    {
                            Response.StatusCode 
    = 206;
                            p 
    = long.Parse( Request.Headers["Range"].Replace("bytes=","").Replace("-",""));
                        }

                        Response.AddHeader(
    "Content-Length", ((long)(l - p)).ToString()); 
                        
    if (p != 0)
                        
    {
                            
    //不是从最开始下载,
                            
    //响应的格式是:
                            
    //Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小]
                            Response.AddHeader("Content-Range","bytes " + p.ToString() + "-" + ((long)(l - p)).ToString() + "/" + l.ToString());
                        }

                        
    long r = sdr.GetBytes(2, p, bytes, 0, bytes.Length);
                        
    while (r == size)
                        
    {
                            Response.OutputStream.Write(bytes,
    0,(int) r);
                            p 
    += size;
                            r 
    = sdr.GetBytes(2, p, bytes, 0, size);
                        }

                        Response.OutputStream.Write(bytes,
    0,(int) r);
                    }

                    
    finally
                    
    {
                        sdr.Close();
                        scn.Close();
                        Response.End();
                    }

                }

                
    else
                
    {
                    Response.Write(
    "Error: can not download your request");
                }

            }


            
    #region Web 窗体设计器生成的代码
            
    override protected void OnInit(EventArgs e)
            
    {
                
    //
                
    // CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
                
    //
                InitializeComponent();
                
    base.OnInit(e);
            }

            
            
    /// <summary>
            
    /// 设计器支持所需的方法 - 不要使用代码编辑器修改
            
    /// 此方法的内容。
            
    /// </summary>

            private void InitializeComponent()
            
    {
                
    this.Load += new System.EventHandler(this.Page_Load);
            }

            
    #endregion

        }

    //}


    另外还有一个:
    .Net/C#: 实现支持断点续传多线程下载的 Http Web 客户端工具类 (第2版) (C# DIY HttpWebClient)
    http://www.cnblogs.com/microshaoft/archive/2005/03/21/122645.aspx

    经测试也已可成功下载,如下测试URL:
    http://localhost/myasp.net/blobdownload.aspx

  • 相关阅读:
    Linux下使用rm删除文件,并排除指定文件
    使用use index优化sql查询
    PHP面试中经常出现的composer 问题总结
    MySQL全局锁库锁表
    《MySQL必懂系列》全局锁、表级锁、行锁
    Redis面试题(2020最新版)
    What is stabs?
    链接与加载
    MachO之Segment初探
    为什么要在预编译头中加__OBJC__?
  • 原文地址:https://www.cnblogs.com/Microshaoft/p/151093.html
Copyright © 2020-2023  润新知