一般项目都会牵涉到文件的存储。都会单独出一个文件服务器。一般文件服务器常见的分成两种协议上传,一种是ftp,一种是http。一般我们用后者比较多。
做法就是在IIS中配置虚拟目录。然后设置该虚拟目录为可读可写。
文件的上传:
第一步,在web.config中配置文件服务器地址:
< fileserver url ="http://10.20.55.128/FileServer/" blockSize ="1048576"maxFileSize ="5000000" acceptFileTypes =".txt|.xml|.rar|.xls|.xlsx|.doc|.docx|.gif|.jpg|.bmp" >
第二步,编写通用的类来处理上传的逻辑:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Configuration; using System.Net; using System.IO; using System.Threading; using System.Text; using System.Diagnostics; using System.Xml; using System.Collections; using Bingosoft.CommonLibrary; /// <summary> /// 上传文件 /// </summary> public static class WebDAVHelper { private static string _targetUrl = ConfigurationManager.AppSettings["CompanyUserPhotoFolder"]; private static int _blockSize = Int32.Parse(ConfigurationManager.AppSettings["BlockSize"]); /// <summary> /// 文件服务器URL /// </summary> public static string TargetUrl { get { return _targetUrl; } set { _targetUrl = value; } } /// <summary> /// 一次写到文件服务器的字节数 /// </summary> public static int BlockSize { get { return _blockSize; } set { _blockSize = value; } } #region FileUpload /// <summary> /// 上传文件 /// </summary> /// <param name="fileName">文件路径</param> /// <param name="stream">输入文件流</param> /// <returns></returns> public static string UploadFile(string fileName, Stream stream) { string url = GetFileUrl(fileName); PrepareWebDirectory(url); if (WebFileDirectoryExist(url)) { DeleteWebFile(url); } UploadFileWithoutPrepareDirectory(stream, url); return url; } /// <summary> /// /// </summary> /// <param name="fileName"></param> /// <returns></returns> public static string GetFileUrl(string fileName) { int i = fileName.IndexOf(":\\"); if (i != -1) return _targetUrl + "/" + fileName.Substring(i + 2).Replace("\\", "/"); else return _targetUrl + "/" + fileName.Replace("\\", "/"); } /// <summary> /// 删除文件/文件夹 /// </summary> /// <param name="fileName">文件路径/文件夹路径</param> public static void DeleteFile(string fileName) { DeleteWebFile(GetFileUrl(fileName)); } /// <summary> /// 下载文件 /// </summary> /// <param name="fileName">文件路径</param> /// <returns></returns> public static HttpWebResponse DownloadFile(string fileName) { //string url = GetFileUrl(fileName); Uri uriTarget = WebDAVHelper.ProcessSpecialCharacters(fileName); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uriTarget); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); return response; } #endregion #region WebDAV private static void DeleteWebFile(string targetUrl) { WebDavOperate(targetUrl, "DELETE"); } private static void UploadFileWithoutPrepareDirectory(Stream stream, string targetUrl) { Uri uri = WebDAVHelper.ProcessSpecialCharacters(targetUrl); System.Net.HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); request.Method = "PUT"; request.Credentials = System.Net.CredentialCache.DefaultCredentials; request.ContentLength = stream.Length; byte[] buffer = new byte[_blockSize]; using (Stream writeStream = request.GetRequestStream()) { using (BinaryReader reader = new BinaryReader(stream)) { int readSizeThisTime; readSizeThisTime = reader.Read(buffer, 0, _blockSize); while (readSizeThisTime > 0) { writeStream.Write(buffer, 0, readSizeThisTime); readSizeThisTime = reader.Read(buffer, 0, _blockSize); Thread.Sleep(0); } } } System.GC.Collect(); } private static bool WebFileDirectoryExist(string targetUrl) { try { GetDirectoryContents(targetUrl, 0); } catch (WebException e) { HttpWebResponse response = (HttpWebResponse)e.Response; if (HttpStatusCode.NotFound == response.StatusCode) { return false; } else { throw e; } } return true; } //************************************************************** // GetDirectoryContents() // - Uses HTTP/DAV to get a list of directories //************************************************************** public static SortedList GetDirectoryContents(string url, int deep) { //Retrieve the File HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(url); Request.Headers.Add("Translate: f"); Request.Credentials = CredentialCache.DefaultCredentials; string requestString = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" + "<a:propfind xmlns:a=\"DAV:\">" + "<a:prop>" + "<a:displayname/>" + "<a:iscollection/>" + "<a:getlastmodified/>" + "</a:prop>" + "</a:propfind>"; Request.Method = "PROPFIND"; if (-1 == deep) { Request.Headers.Add("Depth: infinity"); } else { Request.Headers.Add(string.Format("Depth: {0}", deep)); } Request.ContentLength = requestString.Length; Request.ContentType = "text/xml"; Stream requestStream = Request.GetRequestStream(); requestStream.Write(Encoding.ASCII.GetBytes(requestString), 0, Encoding.ASCII.GetBytes(requestString).Length); requestStream.Close(); HttpWebResponse Response; StreamReader respStream; try { Response = (HttpWebResponse)Request.GetResponse(); respStream = new StreamReader(Response.GetResponseStream()); } catch (WebException e) { Debug.WriteLine("APPMANAGER: Error accessing Url " + url); throw e; } StringBuilder SB = new StringBuilder(); char[] respChar = new char[1024]; int BytesRead = 0; BytesRead = respStream.Read(respChar, 0, 1024); while (BytesRead > 0) { SB.Append(respChar, 0, BytesRead); BytesRead = respStream.Read(respChar, 0, 1024); } respStream.Close(); XmlDocument XmlDoc = new XmlDocument(); XmlDoc.LoadXml(SB.ToString()); //Create an XmlNamespaceManager for resolving namespaces. XmlNamespaceManager nsmgr = new XmlNamespaceManager(XmlDoc.NameTable); nsmgr.AddNamespace("a", "DAV:"); XmlNodeList NameList = XmlDoc.SelectNodes("//a:prop/a:displayname", nsmgr); XmlNodeList isFolderList = XmlDoc.SelectNodes("//a:prop/a:iscollection", nsmgr); XmlNodeList LastModList = XmlDoc.SelectNodes("//a:prop/a:getlastmodified", nsmgr); XmlNodeList HrefList = XmlDoc.SelectNodes("//a:href", nsmgr); SortedList ResourceList = new SortedList(); Resource tempResource; for (int i = 0; i < NameList.Count; i++) { //This check is needed because the PROPFIND request returns the contents of the folder //as well as the folder itself. Exclude the folder. if (HrefList[i].InnerText.ToLower().TrimEnd(new char[] { '/' }) != url.ToLower().TrimEnd(new char[] { '/' })) { tempResource = new Resource(); tempResource.Name = NameList[i].InnerText; tempResource.IsFolder = Convert.ToBoolean(Convert.ToInt32(isFolderList[i].InnerText)); tempResource.Url = HrefList[i].InnerText; tempResource.LastModified = Convert.ToDateTime(LastModList[i].InnerText); ResourceList.Add(tempResource.Url, tempResource); } } return ResourceList; } public static void PrepareWebDirectory(string targetURL) { //先把Url分拆,放入栈中 Stack stackUrls = new Stack(); Uri targetUri = WebDAVHelper.ProcessSpecialCharacters(targetURL); string urlHeader = "http://{0}:{1}"; urlHeader = string.Format(urlHeader, targetUri.Host, targetUri.Port); StringBuilder sbUrlBuilder = new StringBuilder(urlHeader); foreach (string item in targetUri.Segments) { sbUrlBuilder.Append(item); if (item.EndsWith("/")) //确认它是一个文件夹而不是一个文件。 { stackUrls.Push(sbUrlBuilder.ToString()); } } //从Url栈中弹出元素,检查文件夹是否存在,如果不存在,就放到待建URL栈中 Stack stackTobeCreate = new Stack(); string topElement = stackUrls.Pop().ToString(); while (!WebFileDirectoryExist(topElement)) { stackTobeCreate.Push(topElement); if (0 == stackUrls.Count) //空栈 { throw new Exception("没有找到文件服务器。"); } topElement = stackUrls.Pop().ToString(); } //从待建URL栈中取出待建URL,新建文件夹 while (0 < stackTobeCreate.Count) { topElement = stackTobeCreate.Pop().ToString(); WebDavOperate(topElement, "MKCOL"); } } private static void WebDavOperate(string targetURL, string method) { HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(targetURL); Request.Headers.Add("Translate: f"); Request.Credentials = CredentialCache.DefaultCredentials; Request.Method = method; HttpWebResponse Response; try { Response = (HttpWebResponse)Request.GetResponse(); } catch (WebException e) { Debug.WriteLine("APPMANAGER: Error accessing Url " + targetURL); throw e; } } #endregion /// <summary> /// 当上传或下载的文件名包含有特殊字符"#"时,需要执行以下的函数进行处理 /// </summary> /// <param name="Url"></param> /// <returns></returns> private static Uri ProcessSpecialCharacters(string Url) { Uri uriTarget = new Uri(Url); if (!Url.Contains("#")) { return uriTarget; } UriBuilder msPage = new UriBuilder(); msPage.Host = uriTarget.Host; msPage.Scheme = uriTarget.Scheme; msPage.Port = uriTarget.Port; msPage.Path = uriTarget.Fragment; msPage.Fragment = uriTarget.Fragment; Uri uri = msPage.Uri; return uri; } }
文件的下载:
一般文件的下载通过asp.net的Handle去处理。可以任意定义一种扩展类型交给Handle去处理。在Web.config中作如下配置:
< add verb ="*" path ="*.down.ashx" type ="Handler4DownLoadFile" />
Handler4DownLoadFile 是一个后台处理类
代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.IO; using System.Configuration; using System.Data; /// <summary> /// Summary description for Handler4DownLoadFile /// </summary> public class Handler4DownLoadFile : IHttpHandler { public Handler4DownLoadFile() { // // TODO: Add constructor logic here // } public void ProcessRequest(HttpContext context) { string RelAction = context.Request.QueryString["RelAction"]; string FileName = context.Request.QueryString["path"]; string URL = context.Request.QueryString["path"]; Stream fileStream = null; //下载文件权限检验代码Block { //HasPemission(RelAction)?: string ss = ""; } int Size = Convert.ToInt32(ConfigurationManager.AppSettings["ResponseBlockSize"].Trim()); try { //if (HttpUtility.UrlPathEncode(FileName).EndsWith("xls", StringComparison.OrdinalIgnoreCase) || HttpUtility.UrlPathEncode(FileName).EndsWith("doc", StringComparison.OrdinalIgnoreCase)) //{ // string fullfilePath = WebDAVHelper.GetFileUrl(FileName); // UpdateBrowseCount(URL); // context.Response.Redirect(fullfilePath); // return; //} System.Net.HttpWebResponse response = WebDAVHelper.DownloadFile(FileName); fileStream = response.GetResponseStream(); byte[] buffer = new byte[Size]; context.Response.Clear(); context.Response.ContentType = response.ContentType; FileName = Path.GetFileName(FileName); FileName = FileName.Substring(FileName.IndexOf('_') + 1); context.Response.AddHeader("Content-Disposition:", "attachment; filename=" + HttpUtility.UrlPathEncode(FileName)); long toRead = response.ContentLength;//总共需要读的长度 //long toRead = fileStream.Length;//总共需要读的长度 int length;// while (toRead > 0) { if (context.Response.IsClientConnected) { length = fileStream.Read(buffer, 0, Size); context.Response.OutputStream.Write(buffer, 0, length); context.Response.Flush(); toRead = toRead - length; } else { toRead = -1; } } //更新文档的浏览次数 // UpdateBrowseCount(URL); } catch (Exception ex) { throw (new Exception("文件下载出错!"+ex.Message)); //ClientHelper.ShowMessage(this, "error", "文件下载错误!"); //ClientHelper.CloseWindow(this, "error", true); } finally { if (fileStream != null) { fileStream.Close(); fileStream.Dispose(); } } System.GC.Collect(); } public bool IsReusable { get { return true; } } protected void UpdateBrowseCount(string URL) { string sql = string.Format(@"update DocInfo set BrowseCount=BrowseCount+1 from DocInfo di join FileInfo fi on di.DocID=fi.DocID where fi.URL='{0}'", URL); AESDB.Current.ExecuteNonQuery(CommandType.Text, sql); } }