دانلود فایل با قابلیت Resume

در این مقاله قصد داریم نحوه دانلود فایل با قابلیت دانلود ادامه فایل در زمان دیگری را بررسی کنیم .

این کار را میتوانید توسط کلاس زیر انجام دهید

 

using System;
using System.IO;
using System.Web;
using System.Collections;
using System.Data;
using System.Net;
using System.Security.Cryptography;

namespace SoftProjects.WebPresentation.Utility
{
	/// <summary>
	/// Orginal class name is "ZIPHandler" in VB.Net
	/// http://www.devx.com
	/// 
	/// Optimization and convertion by SalarSoft
	/// http://salarsoft.somee.com 
	/// 
	/// Last update: 2008-2-12
	/// </summary>
	public class ResumeDownload : IDisposable
	{
		const string MULTIPART_BOUNDARY = "<q1w2e3r4t5y6u7i8o9p0>";
		const string MULTIPART_CONTENTTYPE = "multipart/byteranges; boundary=" + MULTIPART_BOUNDARY;

		//Response.AddHeader("Content-Disposition","attachment; filename=" + Path.GetFileName(fUrl));
		const string HTTP_HEADER_Content_Disposition = "Content-Disposition";

		const string HTTP_HEADER_ACCEPT_RANGES = "Accept-Ranges";
		const string HTTP_HEADER_ACCEPT_RANGES_BYTES = "bytes";
		const string HTTP_HEADER_CONTENT_TYPE = "Content-Type";
		const string HTTP_HEADER_CONTENT_RANGE = "Content-Range";
		const string HTTP_HEADER_CONTENT_LENGTH = "Content-Length";
		const string HTTP_HEADER_ENTITY_TAG = "ETag";
		const string HTTP_HEADER_LAST_MODIFIED = "Last-Modified";
		const string HTTP_HEADER_RANGE = "Range";
		const string HTTP_HEADER_IF_RANGE = "If-Range";
		const string HTTP_HEADER_IF_MATCH = "If-Match";
		const string HTTP_HEADER_IF_NONE_MATCH = "If-None-Match";
		const string HTTP_HEADER_IF_MODIFIED_SINCE = "If-Modified-Since";
		const string HTTP_HEADER_IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
		const string HTTP_HEADER_UNLESS_MODIFIED_SINCE = "Unless-Modified-Since";

		const string HTTP_METHOD_GET = "GET";
		const string HTTP_METHOD_HEAD = "HEAD";

		private string fContentType = "application/octet-stream";

		public string ContentType
		{
			get { return fContentType; }
			set { fContentType = value; }
		}

		public void Dispose()
		{
		}

		public void ClearResponseData()
		{
			HttpResponse objResponse = HttpContext.Current.Response;
			objResponse.ClearContent();
			objResponse.ClearHeaders();
		}

		public DownloadState ProcessDownload(string fileName,string headerFileName)
		{

			HttpContext objContext = HttpContext.Current;
			// The Response object from the Context
			HttpResponse objResponse = objContext.Response;
			// The Request object from the Context
			HttpRequest objRequest = objContext.Request;

			// File information object...
			FileInformation objFile;

			// Long Arrays for Range values:
			// ...Begin() contains start positions for each requested Range
			long[] alRequestedRangesBegin = new long[1];
			// ...End() contains end positions for each requested Range
			long[] alRequestedRangesend = new long[1];

			// Response Header value: Content Length...
			int iResponseContentLength = 0;

			// The Stream we//re using to download the file in chunks...
			System.IO.Stream objStream;
			// Total Bytes to read (per requested range)
			int iBytesToRead;
			// Size of the Buffer for chunk-wise reading
			int iBufferSize = 25000;
			// The Buffer itself
			byte[] bBuffer = new byte[iBufferSize];
			// Amount of Bytes read
			int iLengthOfReadChunk = -1;

			// Indicates if the download was interrupted
			bool bDownloadBroken = false;

			// Indicates if this is a range request 
			bool bIsRangeRequest = false;
			// Indicates if this is a multipart range request
			bool bMultipart = false;

			// Loop counter used to iterate through the ranges
			int iLoop;

			if (string.IsNullOrEmpty(headerFileName))
				headerFileName = Path.GetFileName(fileName).Replace(' ', '-');

			// Content-Disposition value
			string Content_Disposition_File = "attachment; filename=" + headerFileName + "";

			// ToDo - your code here (Determine which file is requested)
			// Using objRequest, determine which file is requested to
			// be downloaded, and open objFile with that file:
			// Example:
			// objFile = New Download.FileInformation(<Full path to the requested file>)
			//objFile = new Download.FileInformation(objContext.Server.MapPath("~/download.zip"));
			objFile = new FileInformation(fileName);
			objFile.ContentType = this.ContentType;

			// Clear the current output content from the buffer
			objResponse.Clear();

			if (!(objRequest.HttpMethod.Equals(HTTP_METHOD_GET) ||
				objRequest.HttpMethod.Equals(HTTP_METHOD_HEAD)))
				// Currently, only the GET and HEAD methods 
				// are supported...
				objResponse.StatusCode = 501;  // Not implemented

			else if (!objFile.Exists)
				// The requested file could not be retrieved...
				objResponse.StatusCode = 404;  // Not found

			else if (objFile.Length > Int32.MaxValue)
				// The file size is too large... 
				objResponse.StatusCode = 413;  // Request Entity Too Large

			else if (!ParseRequestHeaderRange(objRequest, ref alRequestedRangesBegin, ref alRequestedRangesend,
				objFile.Length, ref bIsRangeRequest))
				// The Range request contained bad entries
				objResponse.StatusCode = 400;  // Bad Request

			else if (!CheckIfModifiedSince(objRequest, objFile))
				// The entity is still unmodified...
				objResponse.StatusCode = 304;  // Not Modified

			else if (!CheckIfUnmodifiedSince(objRequest, objFile))
				// The entity was modified since the requested date... 
				objResponse.StatusCode = 412;  // Precondition failed

			else if (!CheckIfMatch(objRequest, objFile))
				// The entity does not match the request... 
				objResponse.StatusCode = 412;  // Precondition failed

			else if (!CheckIfNoneMatch(objRequest, objResponse, objFile))
			{
				// The entity does match the none-match request, the response 
				// code was set inside the CheckifNoneMatch function
			}
			else
			{
				// Preliminary checks where successful... 

				if (bIsRangeRequest && CheckIfRange(objRequest, objFile))
				{
					// This is a Range request... 

					// if the Range arrays contain more than one entry,
					// it even is a multipart range request...
					bMultipart = (alRequestedRangesBegin.GetUpperBound(0) > 0);

					// Loop through each Range to calculate the entire Response length
					for (iLoop = alRequestedRangesBegin.GetLowerBound(0); iLoop <= alRequestedRangesBegin.GetUpperBound(0); iLoop++)
					{
						// The length of the content (for this range)
						iResponseContentLength += Convert.ToInt32(alRequestedRangesend[iLoop] - alRequestedRangesBegin[iLoop]) + 1;

						if (bMultipart)
						{
							//
							iResponseContentLength += HTTP_HEADER_Content_Disposition.Length;
							// if this is a multipart range request, calculate 
							// the length of the intermediate headers to send
							iResponseContentLength += MULTIPART_BOUNDARY.Length;
							iResponseContentLength += objFile.ContentType.Length;
							iResponseContentLength += alRequestedRangesBegin[iLoop].ToString().Length;
							iResponseContentLength += alRequestedRangesend[iLoop].ToString().Length;
							iResponseContentLength += objFile.Length.ToString().Length;
							// 49 is the length of line break and other 
							// needed characters in one multipart header
							iResponseContentLength += 49;
						}

					}

					if (bMultipart)
					{
						// if this is a multipart range request,  
						// we must also calculate the length of 
						// the last intermediate header we must send
						iResponseContentLength += MULTIPART_BOUNDARY.Length;
						// 8 is the length of dash and line break characters
						iResponseContentLength += 8;
					}
					else
					{
						// This is no multipart range request, so
						// we must indicate the response Range of 
						// in the initial HTTP Header 
						objResponse.AppendHeader(HTTP_HEADER_CONTENT_RANGE, "bytes " +
							alRequestedRangesBegin[0].ToString() + "-" +
							alRequestedRangesend[0].ToString() + "/" +
							objFile.Length.ToString());
					}

					// Range response 
					objResponse.StatusCode = 206; // Partial Response

				}
				else
				{
					// This is not a Range request, or the requested Range entity ID
					// does not match the current entity ID, so start a new download

					// Indicate the file//s complete size as content length
					iResponseContentLength = Convert.ToInt32(objFile.Length);

					// Return a normal OK status...
					objResponse.StatusCode = 200;
				}


				// Write file name into the Response
				objResponse.AppendHeader(HTTP_HEADER_Content_Disposition, Content_Disposition_File);

				// Write the content length into the Response
				objResponse.AppendHeader(HTTP_HEADER_CONTENT_LENGTH, iResponseContentLength.ToString());

				// Write the Last-Modified Date into the Response
				objResponse.AppendHeader(HTTP_HEADER_LAST_MODIFIED, objFile.LastWriteTimeUTC.ToString("r"));

				// Tell the client software that we accept Range request
				objResponse.AppendHeader(HTTP_HEADER_ACCEPT_RANGES, HTTP_HEADER_ACCEPT_RANGES_BYTES);

				// Write the file//s Entity Tag into the Response (in quotes!)
				objResponse.AppendHeader(HTTP_HEADER_ENTITY_TAG, "\"" + objFile.EntityTag + "\"");


				// Write the Content Type into the Response
				if (bMultipart)
					// Multipart messages have this special Type.
					// In this case, the file//s actual mime type is
					// written into the Response at a later time...
					objResponse.ContentType = MULTIPART_CONTENTTYPE;
				else
					// Single part messages have the files content type...
					objResponse.ContentType = objFile.ContentType;


				if (objRequest.HttpMethod.Equals(HTTP_METHOD_HEAD))
				{
					// Only the HEAD was requested, so we can quit the Response right here... 
				}
				else
				{

					// Flush the HEAD information to the client...
					objResponse.Flush();

					// Download is in progress...
					objFile.State = DownloadState.fsDownloadInProgress;

					// Open the file as filestream
					objStream = new FileStream(objFile.FullName, FileMode.Open,
						FileAccess.Read,
						FileShare.Read);
					try
					{

						//objStream = objFile.DataStream;

						// Now, for each requested range, stream the chunks to the client:
						for (iLoop = alRequestedRangesBegin.GetLowerBound(0); iLoop <= alRequestedRangesBegin.GetUpperBound(0); iLoop++)
						{

							// Move the stream to the desired start position...
							objStream.Seek(alRequestedRangesBegin[iLoop], SeekOrigin.Begin);

							// Calculate the total amount of bytes for this range
							iBytesToRead = Convert.ToInt32(alRequestedRangesend[iLoop] - alRequestedRangesBegin[iLoop]) + 1;

							if (bMultipart)
							{
								// if this is a multipart response, we must add 
								// certain headers before streaming the content:

								// The multipart boundary
								objResponse.Output.WriteLine("--" + MULTIPART_BOUNDARY);
								//objResponse.AppendHeader("--",MULTIPART_BOUNDARY);

								// The mime type of this part of the content 
								objResponse.Output.WriteLine(HTTP_HEADER_CONTENT_TYPE + ": " + objFile.ContentType);
								//objResponse.AppendHeader(HTTP_HEADER_CONTENT_TYPE,objFile.ContentType);

								// The actual range
								objResponse.Output.WriteLine(HTTP_HEADER_CONTENT_RANGE + ": bytes " +
									alRequestedRangesBegin[iLoop].ToString() + "-" +
									alRequestedRangesend[iLoop].ToString() + "/" +
									objFile.Length.ToString());

								/*objResponse.AppendHeader(HTTP_HEADER_CONTENT_RANGE,": bytes " +
									alRequestedRangesBegin[iLoop].ToString() + "-" +
									alRequestedRangesend[iLoop].ToString() + "/" +
									objFile.Length.ToString());
								*/
								// Indicating the end of the intermediate headers
								objResponse.Output.WriteLine();

							}

							// Now stream the range to the client...
							while (iBytesToRead > 0)
							{

								if (objResponse.IsClientConnected)
								{
									// Read a chunk of bytes from the stream
									iLengthOfReadChunk = objStream.Read(bBuffer, 0, Math.Min(bBuffer.Length, iBytesToRead));

									// Write the data to the current output stream.
									objResponse.OutputStream.Write(bBuffer, 0, iLengthOfReadChunk);

									// Flush the data to the HTML output.
									objResponse.Flush();

									// Clear the buffer
									bBuffer = new byte[iBufferSize];
									//ReDim bBuffer(iBufferSize);

									// Reduce BytesToRead
									iBytesToRead -= iLengthOfReadChunk;
								}
								else
								{
									// The client was or has disconneceted from the server... stop downstreaming...
									iBytesToRead = -1;
									bDownloadBroken = true;

								}
							}

							// In Multipart responses, mark the end of the part 
							if (bMultipart) objResponse.Output.WriteLine();

							// No need to proceed to the next part if the 
							// client was disconnected
							if (bDownloadBroken) break;
						}

						// At this point, the response was finished or cancelled... 

						if (bDownloadBroken)
							// Download is broken...
							objFile.State = DownloadState.fsDownloadBroken;

						else
						{
							if (bMultipart)
							{
								// In multipart responses, close the response once more with 
								// the boundary and line breaks
								objResponse.Output.WriteLine("--" + MULTIPART_BOUNDARY + "--");
								objResponse.Output.WriteLine();
							}

							// The download was finished
							objFile.State = DownloadState.fsDownloadFinished;
						}
					}
					finally
					{
						objStream.Close();
					}
				}
			}
			//objResponse.End();

			//====== return download state ======
			return objFile.State;
		}


		bool CheckIfRange(HttpRequest objRequest, FileInformation objFile)
		{
			string sRequestHeaderIfRange;

			// Checks the If-Range header if it was sent with the request.
			//
			// returns true if the header value matches the file//s entity tag,
			//              or if no header was sent,
			// returns false if a header was sent, but does not match the file.


			// Retrieve If-Range Header value from Request (objFile.EntityTag if none is indicated)
			sRequestHeaderIfRange = RetrieveHeader(objRequest, HTTP_HEADER_IF_RANGE, objFile.EntityTag);

			// If the requested file entity matches the current
			// file entity, return true
			return sRequestHeaderIfRange.Equals(objFile.EntityTag);
		}

		bool CheckIfMatch(HttpRequest objRequest, FileInformation objFile)
		{
			string sRequestHeaderIfMatch;
			string[] sEntityIDs;
			bool breturn = false;

			// Checks the If-Match header if it was sent with the request.
			//
			// returns true if one of the header values matches the file//s entity tag,
			//              or if no header was sent,
			// returns false if a header was sent, but does not match the file.


			// Retrieve If-Match Header value from Request (*, meaning any, if none is indicated)
			sRequestHeaderIfMatch = RetrieveHeader(objRequest, HTTP_HEADER_IF_MATCH, "*");

			if (sRequestHeaderIfMatch.Equals("*"))
				// The server may perform the request as if the
				// If-Match header does not exists...
				breturn = true;

			else
			{
				// One or more Match IDs where sent by the client software...
				sEntityIDs = sRequestHeaderIfMatch.Replace("bytes=", "").Split(",".ToCharArray());

				// Loop through all entity IDs, finding one 
				// which matches the current file's ID will
				// be enough to satisfy the If-Match
				for (int iLoop = sEntityIDs.GetLowerBound(0); iLoop <= sEntityIDs.GetUpperBound(0); iLoop++)
				{
					if (sEntityIDs[iLoop].Trim().Equals(objFile.EntityTag))
						breturn = true;
				}
			}
			// return the result...
			return breturn;
		}

		bool CheckIfNoneMatch(HttpRequest objRequest, HttpResponse objResponse, FileInformation objFile)
		{
			string sRequestHeaderIfNoneMatch;
			string[] sEntityIDs;
			bool breturn = true;
			string sreturn = "";
			// Checks the If-None-Match header if it was sent with the request.
			//
			// returns true if one of the header values matches the file//s entity tag,
			//              or if "*" was sent,
			// returns false if a header was sent, but does not match the file, or
			//               if no header was sent.

			// Retrieve If-None-Match Header value from Request (*, meaning any, if none is indicated)
			sRequestHeaderIfNoneMatch = RetrieveHeader(objRequest, HTTP_HEADER_IF_NONE_MATCH, String.Empty);

			if (sRequestHeaderIfNoneMatch.Equals(String.Empty))
				// Perform the request normally...
				breturn = true;
			else
			{
				if (sRequestHeaderIfNoneMatch.Equals("*"))
				{
					// The server must not perform the request 
					objResponse.StatusCode = 412;  // Precondition failed
					breturn = false;
				}
				else
				{
					// One or more Match IDs where sent by the client software...
					sEntityIDs = sRequestHeaderIfNoneMatch.Replace("bytes=", "").Split(",".ToCharArray());

					// Loop through all entity IDs, finding one which 
					// does not match the current file//s ID will be
					// enough to satisfy the If-None-Match
					for (int iLoop = sEntityIDs.GetLowerBound(0); iLoop <= sEntityIDs.GetUpperBound(0); iLoop++)
					{
						if (sEntityIDs[iLoop].Trim().Equals(objFile.EntityTag))
						{
							sreturn = sEntityIDs[iLoop];
							breturn = false;
						}
					}

					if (!breturn)
					{
						// One of the requested entities matches the current file//s tag,
						objResponse.AppendHeader("ETag", sreturn);
						objResponse.StatusCode = 304; // Not Modified
					}
				}
			}
			// return the result...
			return breturn;
		}

		bool CheckIfModifiedSince(HttpRequest objRequest, FileInformation objFile)
		{
			string sDate;
			DateTime dDate;
			bool breturn;

			// Checks the If-Modified header if it was sent with the request.
			//
			// returns true, if the file was modified since the 
			//               indicated date (RFC 1123 format), or
			//               if no header was sent,
			// returns false, if the file was not modified since
			//                the indicated date


			// Retrieve If-Modified-Since Header value from Request (Empty if none is indicated)
			sDate = RetrieveHeader(objRequest, HTTP_HEADER_IF_MODIFIED_SINCE, string.Empty);

			if (sDate.Equals(String.Empty))
				// No If-Modified-Since date was indicated, 
				// so just give this as true 
				breturn = true;

			else
			{
				try
				{
					// ... to parse the indicated sDate to a datetime value
					dDate = DateTime.Parse(sDate);
					// return true if the file was modified since or at the indicated date...
					breturn = (objFile.LastWriteTimeUTC >= DateTime.Parse(sDate));
				}
				catch
				{
					// Converting the indicated date value failed, return false 
					breturn = false;
				}
			}
			return breturn;
		}

		bool CheckIfUnmodifiedSince(HttpRequest objRequest, FileInformation objFile)
		{
			string sDate;
			DateTime dDate;
			bool breturn;


			// Checks the If-Unmodified or Unless-Modified-Since header, if 
			// one of them was sent with the request.
			//
			// returns true, if the file was not modified since the 
			//               indicated date (RFC 1123 format), or
			//               if no header was sent,
			// returns false, if the file was modified since the indicated date


			// Retrieve If-Unmodified-Since Header value from Request (Empty if none is indicated)
			sDate = RetrieveHeader(objRequest, HTTP_HEADER_IF_UNMODIFIED_SINCE, String.Empty);

			if (sDate.Equals(String.Empty))
				// If-Unmodified-Since was not sent, check Unless-Modified-Since... 
				sDate = RetrieveHeader(objRequest, HTTP_HEADER_UNLESS_MODIFIED_SINCE, String.Empty);


			if (sDate.Equals(String.Empty))
				// No date was indicated, 
				// so just give this as true 
				breturn = true;

			else
			{
				try
				{
					// ... to parse the indicated sDate to a datetime value
					dDate = DateTime.Parse(sDate);
					// return true if the file was not modified since the indicated date...
					breturn = objFile.LastWriteTimeUTC < DateTime.Parse(sDate);
				}
				catch
				{
					// Converting the indicated date value failed, return false 
					breturn = false;
				}
			}
			return breturn;
		}

		bool ParseRequestHeaderRange(HttpRequest objRequest, ref long[] lBegin, ref long[] lEnd , long lMax , ref bool bRangeRequest)
		{
			bool bValidRanges;
			string sSource;
			int iLoop;
			string[] sRanges;

			// Parses the Range header from the Request (if there is one)
			// returns true, if the Range header was valid, or if there was no 
			//               Range header at all (meaning that the whole 
			//               file was requested)
			// returns false, if the Range header asked for unsatisfieable 
			//                ranges

			// Retrieve Range Header value from Request (Empty if none is indicated)
			sSource = RetrieveHeader(objRequest, HTTP_HEADER_RANGE, String.Empty);

			if (sSource.Equals(String.Empty))
			{
				// No Range was requested, return the entire file range...

				lBegin = new long[1];
				//ReDim lBegin(0);
				lEnd = new long[1];
				//ReDim lEnd(0);

				lBegin[0] = 0;
				lEnd[0] = lMax - 1;

				// A valid range is returned
				bValidRanges = true;
				// no Range request
				bRangeRequest = false;
			}
			else
			{
				// A Range was requested... 

				// Preset value...
				bValidRanges = true;

				// return true for the bRange parameter, telling the caller
				// that the Request is indeed a Range request...
				bRangeRequest = true;

				// Remove "bytes=" from the beginning, and split the remaining 
				// string by comma characters
				sRanges = sSource.Replace("bytes=", "").Split(",".ToCharArray());
				lBegin = new long[sRanges.GetUpperBound(0) + 1];
				//ReDim lBegin(sRanges.GetUpperBound(0));
				lEnd = new long[sRanges.GetUpperBound(0) + 1];
				//ReDim lEnd(sRanges.GetUpperBound(0));

				// Check each found Range request for consistency
				for (iLoop = sRanges.GetLowerBound(0); iLoop <= sRanges.GetUpperBound(0); iLoop++)
				{

					// Split this range request by the dash character, 
					// sRange(0) contains the requested begin-value,
					// sRange(1) contains the requested end-value...
					string[] sRange = sRanges[iLoop].Split("-".ToCharArray());

					// Determine the end of the requested range
					if (sRange[1].Equals(String.Empty))
						// No end was specified, take the entire range
						lEnd[iLoop] = lMax - 1;
					else
						// An end was specified...
						lEnd[iLoop] = long.Parse(sRange[1]);

					// Determine the begin of the requested range
					if (sRange[0].Equals(String.Empty))
					{
						// No begin was specified, which means that
						// the end value indicated to return the last n
						// bytes of the file:

						// Calculate the begin
						lBegin[iLoop] = lMax - 1 - lEnd[iLoop];
						// ... to the end of the file...
						lEnd[iLoop] = lMax - 1;
					}
					else
						// A normal begin value was indicated...
						lBegin[iLoop] = long.Parse(sRange[0]);


					// Check if the requested range values are valid, 
					// return false if they are not.
					//
					// Note:
					// Do not clean invalid values up by fitting them into
					// valid parameters using Math.Min and Math.Max, because
					// some download clients (like Go!Zilla) might send invalid 
					// (e.g. too large) range requests to determine the file limits!

					// Begin and end must not exceed the file size
					if ((lBegin[iLoop] > (lMax - 1)) || (lEnd[iLoop] > (lMax - 1)))
						bValidRanges = false;

					// Begin and end cannot be < 0
					if ((lBegin[iLoop] < 0) || (lEnd[iLoop] < 0))
						bValidRanges = false;

					// End must be larger or equal to begin value
					if (lEnd[iLoop] < lBegin[iLoop])
						// The requested Range is invalid...
						bValidRanges = false;

				}

			}
			return bValidRanges;
		}

		string RetrieveHeader(HttpRequest objRequest, string sHeader,string sDefault)
		{
			string sreturn;

			// Retrieves the indicated Header//s value from the Request,
			// if the header was not sent, sDefault is returned.
			//
			// If the value contains quote characters, they are removed.

			sreturn = objRequest.Headers[sHeader];

			if ((sreturn == null) || (sreturn.Equals(string.Empty)))
				// The Header wos not found in the Request, 
				// return the indicated default value...
				return sDefault;

			else
				// return the found header value, stripped of any quote characters...
				return sreturn.Replace("\"", "");

		}


		string GenerateHash(System.IO.Stream objStream, long lBegin ,long lEnd)
		{
			byte[] bByte = new byte[Convert.ToInt32(lEnd)];

			objStream.Read(bByte, Convert.ToInt32(lBegin), Convert.ToInt32(lEnd - lBegin) + 1);

			//Instantiate an MD5 Provider object
			MD5CryptoServiceProvider Md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();

			//Compute the hash value from the source
			byte[] ByteHash = Md5.ComputeHash(bByte);

			//And convert it to String format for return
			return Convert.ToBase64String(ByteHash);
		}

	}

	public class FileInformation
	{
		DownloadState m_nState;
		DateTime fCreatTime;
		string fFileName = "";
		string m_ContentType = "application/octet-stream";
		long? fileLength = null;

		public FileInformation(string fileName)
		{
			fFileName = fileName;
			fCreatTime = DateTime.Now;
		}

		public bool Exists
		{
			get
			{
				return File.Exists(fFileName);
			}
		}

		public string FullName
		{
			get { return fFileName;/*m_objFile.FullName;*/}
		}

		public DateTime LastWriteTimeUTC
		{
			get { return fCreatTime.ToUniversalTime(); }
		}
		public long Length
		{
			get
			{
				if (fileLength.HasValue == false)
				{
					FileInfo info = new FileInfo(fFileName);
					fileLength = info.Length;
				}
				return fileLength.Value;

			}
		}

		public string ContentType
		{
			get
			{
				return m_ContentType;
			}
			set
			{
				m_ContentType = value;
			}
		}
		public string EntityTag
		{
			get
			{
				return fFileName.GetHashCode().ToString();//"MyExampleFileID";
			}
		}
		public virtual DownloadState State
		{
			get
			{
				return m_nState;
			}
			set
			{
				m_nState = value;
			}
		}
	}


	public enum DownloadState
	{
		/// Clear: No download in progress, 
		/// the file can be manipulated
		fsClear = 1,

		/// Locked: A dynamically created file must
		/// not be changed
		fsLocked = 2,

		/// In Progress: File is locked, and download 
		/// is currently in progress
		fsDownloadInProgress = 6,

		/// Broken: File is locked, download was in
		/// progress, but was cancelled 
		fsDownloadBroken = 10,

		/// Finished: File is locked, download
		/// was completed
		fsDownloadFinished = 18
	};
}

 

فایل های ضمیمه