zoukankan      html  css  js  c++  java
  • c#文件上传下载之基本流程

          前几天做了个文件上传下载的例子,就是对Blob对象的上传下载,现把其中遇到的问题以及解决方法在这里再顺一遍。

          大家都知道我们的文件是保存在硬盘,也就是外存中的,那我们在上传的时候就要先把文件调入到内存。而内存的容量是有限的,如果我们的文件过于庞大,就会占用太多的内存,所以我们就要把文件分块,然后再把文件一块一块的读入到内存缓冲区中,然后再把缓冲区中的数据读到数据库Blob对象里。那这个Blob对象又是哪来的呢,这就要求我们先向数据库中注册文件的其它信息,包括文件名,文件类型,上传时间等信息,然后同时返回Blob对象名。所以我们需要建一个类来保存文件的信息,以及控制对文件的读写。好,上传大概就是这么一个过程,那下面我们来结合代码再顺一遍。

    • 先对一些变量进行初始化 ,这些变量都是文件类fileInfo里的。
    buffer = new byte[blockSize];//建立缓冲区数组
    inputStream = new FileStream(path , FileMode.Open, FileAccess.Read, FileShare.Read,4* 1024*1024, true);//建立读文件的数据流 fileSize = inputStream.Length;//获取文件大小 blockCount = (int)(fileSize / blockSize)+1;//对文件进行分块
    • 对文件其它信息进行注册,并返回Blob对象
    private OracleTransaction insert()//注册文件信息
    {
                    OracleConnection conn = new OracleConnection(connString);
               
                    OracleCommand cmd = new OracleCommand("system.form_zhu.file_insert", conn);
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.BindByName = true;
    
    
                    OracleParameter para_fileName = new OracleParameter("paraName", fileInfo.fileName);//文件名
                    para_fileName.Direction = ParameterDirection.Input;
                    cmd.Parameters.Add(para_fileName);
    
                    OracleParameter para_fileType = new OracleParameter("paraType", fileInfo.fileType);//类型
                    para_fileType.Direction = ParameterDirection.Input;
                    cmd.Parameters.Add(para_fileType);
    
                    OracleParameter where_string = new OracleParameter("paraString", OracleDbType.Varchar2);//返回where_string
                    where_string.Direction = ParameterDirection.Output;
                    where_string.Size = 200;
                    cmd.Parameters.Add(where_string);
    
                    conn.Open();
                    OracleTransaction txn = conn.BeginTransaction();//开启事务
    cmd.ExecuteNonQuery();


    此处用了事务处理,注册的时候开启事务,直到写完成的的时候结束事务,以遍读写中断的时候可以回滚重新进行读写。

     private void blob(OracleTransaction txn)//获取Blob对象
           {
               
    
                    OracleCommand cmd = new OracleCommand("system.FORM_ZHU.getBlob", txn.Connection);
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.BindByName = true;
    
                    OracleParameter para_tableName = new OracleParameter("tableName", this .tableName );//表名
                    para_tableName.Direction = ParameterDirection.Input;
                    cmd.Parameters.Add(para_tableName);
    
                    OracleParameter para_blobName = new OracleParameter("blobName", this.blobName );//Blob对象列名
                    para_blobName.Direction = ParameterDirection.Input;
                    cmd.Parameters.Add(para_blobName);
    
                    OracleParameter para_Wblob = new OracleParameter("whereString",whereString );//Blob对象地址
                    para_Wblob.Direction = ParameterDirection.Input;
                    cmd.Parameters.Add(para_Wblob);
    
    
                    OracleParameter blob = new OracleParameter("temp_blob", OracleDbType.Blob);//返回Blob对象
                    blob.Direction = ParameterDirection.ReturnValue ;
                    blob.Size = 200000;
                    cmd.Parameters.Add(blob);
    
                    cmd.ExecuteNonQuery();
                    fileContent =(OracleBlob ) blob.Value;

    此处用的连接还是上面事务的连接,用来获取OracleBlob对象,赋值给FileInfo类的FileContent变量。

    • 然后主窗体调用FileInfo里的Read方法,此处的读写为异步读写。何为异步读写,就是开辟另一个线程,和主线程同时在运行,互不干扰。比如说子线程在进行读写的时候,主窗体的进度条随着读写的进度在变化。
     读写
     1 public void ReadFileToBuffer()
     2         {
     3             inputStream.BeginRead(buffer, 0, blockSize, WriteFileToBlob, null);//以Begin开头的表示为异步方式,将一块文件读到Buffer里,读完了就调用WriteFileToBlob回调函数
     4         }
     5         public void WriteFileToBlob(IAsyncResult a)
     6         {
     7             inputStream.EndRead(a);//结束读这一线程
     8             if (i < blockCount)//不是最后一块的时候,将Buffer里的数据写到FileContent这个OracleBlob对象里,写完后调用OnEndWrite1回调函数。
     9             {
    10                 fileContent.BeginWrite(buffer, 0, blockSize, OnEndWrite1, null);
    11 
    12             }
    13             if (i == blockCount)//最后一块
    14             {
    15                 fileContent.BeginWrite(buffer, 0, (int)fileSize % blockSize, OnEndWrite2, null);
    16             }
    17         }
    18         private void OnEndWrite1(IAsyncResult a)
    19         {
    20             OnFileBuffer(new EventArgs());//读一块引发的事件,此处不说
    21             fileContent.EndWrite(a);
    22             i++;
    23             ReadFileToBuffer();
    24         }
    25         private void OnEndWrite2(IAsyncResult a)
    26         {
    27             _txn.Commit();//关闭事务流,结束读写
    28             OnFileUpdateComplete(new EventArgs());
    29         }

          下载就是上传的一个逆过程,上传懂了下载也就会了,此处不再赘述。

         

  • 相关阅读:
    mysql命令集锦
    linux 删除文件名带括号的文件
    linux下的cron定时任务
    struts2文件下载的实现
    贴一贴自己写的文件监控代码python
    Service Unavailable on IIS6 Win2003 x64
    'style.cssText' is null or not an object
    "the current fsmo could not be contacted" when change rid role
    远程激活程序
    新浪图片病毒
  • 原文地址:https://www.cnblogs.com/ddan/p/2645127.html
Copyright © 2011-2022 走看看