一般项目都会牵涉到文件的存储。都会单独出一个文件服务器。一般文件服务器常见的分成两种协议上传,一种是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);
}
}