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         }

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

         

  • 相关阅读:
    终端启动jupyter notebook需要配置环境变量
    利用requests模块进行数据爬取初级操作
    爬虫初识
    Xadmin使用
    Vue 前端框架中限制用户短时间内多次点击同一按钮的方法(例如:登录、注册)
    Django利用Xadmin作为后台管理系统且在后台显示自定义的APP名称
    MySQL数据库中创建新用户,并将某个指定库的操作权限赋予此用户。。。
    MySQL数据库中删除用户的两种方法
    MySQL数据库中如何查询所有用户
    Django 版本升级
  • 原文地址:https://www.cnblogs.com/ddan/p/2645127.html
Copyright © 2011-2022 走看看