网上很多文件上传下载的文章,多数是采用http方式,使用.net的webcliend的功能,此功能对大文件效率比较低,对web服务器安全性也有影响。
我采用数据库的方式同样实现并高效的处理了此功能,对于数据库winform应用值得借鉴。
开发思路(以下思路是c/s三层架构,中间需要有webservice服务):
1 把数据存于数据库也可以不存入数据库,如果存入数据库就要在表中增加image字段存放byte数据。
2 采filestream对像,对文件进行读写操作,不管是存入数据库还是以文件形式上传到服务器的文件系统中
上传部分选择文件都是相同的,都需要用到数据表,如果要存入数据库就要建表,如果不存入数据库可以
用sql语句虚拟一个表结构:如Select file_Id=0,file_name='',convert(image,null) file_data where 1<>1
3 如果是把文件存入web服务器,在webservice中需要有上传和下载的函数。上传时就是把dataset中的byte还原
成文件流fileStream,再把文件写入文件系统(此方式要设置iis对文件系统的写的权限,不然会提示拒绝访问);
下载就是根据文件名用fileStream把文件从文件系统中读取来,再以byte的形式放入dataset.table中。
4 文件的另存,文件的另存把datatabel中的byte写入filestream中,再写入客户端的文件系统中。
以下是开发的全代码:
1 此段是用文件打开控件选择文件,把文件写入table的对应的路径中。
private void btnBrowse_Click(object sender, EventArgs e)
{
OpenFileDialog filedlg = new OpenFileDialog();
filedlg.Multiselect = true;
if (filedlg.ShowDialog() == DialogResult.OK)
{
string[] filenames = filedlg.FileNames;
for (int i = 0; i < filenames.Length; i++)
{
string fileName = filenames[i];
int n = fileName.LastIndexOf(@"\");
string file = fileName.Substring(n + 1, fileName.Length - n - 1);
sDH=dgvMSG.CurrentRow.Cells["MSG_DH"].Value.ToString();
if (File.Exists(fileName))
{
DataRow[] dr1=dsMSG .Tables ["MSG_DOC"].Select ("MSGDOC_DH='"+sDH +"' AND MSGDOC_FILENAME='"+file +"'");
if (dr1.Length <=0)
{
DataRow dr = dsMSG.Tables["MSG_DOC"].NewRow();
dr["MSGDOC_DH"] = sDH;
dr["MSGDOC_FILENAME"] = file;
FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
byte[] bt = new byte[fs.Length];
fs.Position = 0;
fs.Read(bt, 0, Convert.ToInt32(fs.Length));
dr["MSGDOC_FILE"] = bt;
dsMSG.Tables["MSG_DOC"].Rows.Add(dr);
lbFILES.Items.Add(file);
}
}
}
btnSAVEAS.Enabled = (lbFILES.Items.Count > 0);
}
}
2 下面是把table中的文件流另存到客户端文件
private void btnSAVEAS_Click(object sender, EventArgs e)
{
if (lbFILES.SelectedItems.Count > 0 && dgvMSG .Rows .Count >0)
{
string sDH = dgvMSG.CurrentRow.Cells["MSG_DH"].Value.ToString();
FolderBrowserDialog fld = new FolderBrowserDialog();
if (fld.ShowDialog ()== DialogResult.OK)
{
waiting w = new waiting();
try
{
w.Show();
DataSet dsMSG_DOC = Query_MSG_DOC(sDH);
string path = fld.SelectedPath;
if (!path.EndsWith(@"\"))//判斷是否為根目錄,如果不是根目錄要添加分隔符"\"
path += @"\";
for (int i = 0; i < lbFILES.SelectedItems.Count; i++)
{
string sFilename = lbFILES.SelectedItems[i].ToString();
DataRow[] dr = dsMSG_DOC.Tables["MSG_DOC"].Select("MSGDOC_DH='" + sDH + "' AND MSGDOC_FILENAME='" + sFilename + "'");
if (dr.Length > 0 && dr[0]["MSGDOC_FILE"] != null)
{
byte[] btFile = (byte[])dr[0]["MSGDOC_FILE"];
FileStream fs = new FileStream(path + sFilename, FileMode.Create);
fs.Write(btFile, 0, btFile.Length);
fs.Close();
}
}
}
finally
{
w.Close();
}
}
}
}
private void btnRemove_Click(object sender, EventArgs e)
{
if (!isinBrowse)
{
for (int i = 0; i < lbFILES.SelectedItems.Count; i++)
{
string filename = lbFILES.SelectedItems[i].ToString();
string sDH = dgvMSG.CurrentRow.Cells["MSG_DH"].Value.ToString();
DataRow[] dr = dsMSG.Tables["MSG_DOC"].Select("MSGDOC_DH='" + sDH + "' AND MSGDOC_FILENAME='" + filename + "'");
if (dr.Length > 0)
{
string sID=Convert.ToString (dr[0]["MSGDOC_ID"]);
dsMSG.Tables["MSG_DOC"].Rows.Remove(dr[0]);
string sql = "Delete FROM MSG_DOC WHERE MSGDOC_DH='" + sDH + "'"
+ " AND MSGDOC_ID=" + sID ;
string msgError = "";
POS.SQLcmd_1(BASEINFO.DESEncrypt(sql), Program.userinfo.P_user.U_ID.ToString(), out msgError);
//lbFILES.Items.Remove(lbFILES.SelectedItems[i]);
}
}
object[] selected_objs = new object[lbFILES.SelectedItems.Count];
lbFILES.SelectedItems.CopyTo(selected_objs, 0);
foreach (object oval in selected_objs)
{
lbFILES.Items.Remove(oval);
}
SetToolsBtn();
}
}
4 下面webserve把文件流存入服务器的文件系统中
[WebMethod]
public bool UplodeFiles(byte[] btData, out string errorMsg)
{
try
{
DataSet dsFILE = serverbase.DecompressDS(btData);
DataRow drs = dsFILE.Tables[0].Rows[0];
byte []btFile=(byte[])dsFILE.Tables[0].Rows[0]["FILE_DATA"];
string fileName = Convert.ToString (dsFILE.Tables[0].Rows[0]["FILENAME"]);
FileStream fs = new FileStream(@"D:\" + fileName,FileMode.CreateNew); \\此处为了测试方便用的固定路径,业务上可以通过参数传路径
fs.Write(btFile, 0, btFile.Length);
fs.Close();
errorMsg = "";
return true;
}
catch (Exception E)
{
errorMsg = E.Message.ToString();
return false;
}
finally
{
}
}
5 如果只是存入服务器的文件系统,在第1段代码后面,调用webserve的上传函数就可以了。
增下下面代码 你的webservice.UplodeFiles(BASEINFO.SerializationDataset(dsFILE), out msgError);
6下载文件服务器文件到客户端就是反过来就好了。
7直接双击文件列表打开文件方法如下:
private void lbFILES_DoubleClick(object sender, EventArgs e)
{
if (isinBrowse && lbFILES.Items.Count > 0 && dgvMSG.Rows.Count > 0)
{
string sDH = dgvMSG.CurrentRow.Cells["MSG_DH"].Value.ToString();
DataSet dsMSG_DOC = Query_MSG_DOC(sDH);
string path = System.IO.Path.GetTempPath();//Environment.GetEnvironmentVariable("TEMP");
if (!path.EndsWith(@"\"))//判斷是否為根目錄,如果不是根目錄要添加分隔符"\"
path += @"\";
string sFilename = lbFILES.Items[lbFILES.SelectedIndex].ToString ();
DataRow[] dr = dsMSG_DOC.Tables["MSG_DOC"].Select("MSGDOC_DH='" + sDH + "' AND MSGDOC_FILENAME='" + sFilename + "'");
if (dr.Length > 0 && dr[0]["MSGDOC_FILE"] != null)
{
byte[] btFile = (byte[])dr[0]["MSGDOC_FILE"];
FileStream fs = new FileStream(path + sFilename, FileMode.Create);
fs.Write(btFile, 0, btFile.Length);
System.Diagnostics.Process.Start(path + sFilename);
fs.Close();
}
}
}