Skip to content

Instantly share code, notes, and snippets.

@Hineynu
Created September 12, 2010 23:17
Show Gist options
  • Save Hineynu/576593 to your computer and use it in GitHub Desktop.
Save Hineynu/576593 to your computer and use it in GitHub Desktop.
<%@ Page language="c#" EnableViewState="true" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.OleDb" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script language="C#" runat="server">
// Handle file uploads via XMLHttpRequest
bool fLog = false;
string sLogFileFolder = string.Empty;
void Page_Load(Object Src, EventArgs E )
{
BindData();
}
private void BindData()
{
#region User Configuration
// list of valid extensions, ex. new string[]{"jpeg", "xml", "bmp"}
string[] allowedExtensions = new string[]{};
// max file size in bytes
int sizeLimit = 6 * 1024 * 1024;
// where to save the uploaded files
string uploadDirectory = Server.MapPath("~/images/EL/");
// used to return the url of the uploaded file
string serverPathToWebApplicationRoot = Server.MapPath("..");
// logging, you may also browse to this page with "configcheck=1" as the querystring to verify everything is setup correctly on the server
fLog = false;
sLogFileFolder = Server.MapPath("..\\Logs\\");
#endregion User Configuration
if (fLog)
{
if(Request.QueryString["qqfile"] != null)
WriteToLog("Upload Using UploadHandlerXhr" + Environment.NewLine);
else if(Request.Files.Count > 0)
WriteToLog("Upload Using UploadHandlerForm" + Environment.NewLine);
else
WriteToLog("No Files Uploaded" + Environment.NewLine);
WriteToLog("Request.QueryString[\"qqfile\"]: " + Request.QueryString["qqfile"] + Environment.NewLine);
WriteToLog("Request.Files.Count: " + Request.Files.Count.ToString() + Environment.NewLine);
int loop1 = 0;
string[] arr1 = Request.Files.AllKeys;
for (loop1 = 0; loop1 < arr1.Length; loop1++)
{
WriteToLog("\tRequest.Files.KeyName: " + arr1[loop1] + Environment.NewLine);
WriteToLog("\tRequest.Files[" + loop1.ToString() + "].FileName: " + Request.Files[loop1].FileName + Environment.NewLine);
WriteToLog("\tRequest.Files[" + loop1.ToString() + "].ContentLength: " + Request.Files[loop1].ContentLength + Environment.NewLine);
WriteToLog("\tRequest.Files[" + loop1.ToString() + "].ContentType: " + Request.Files[loop1].ContentType + Environment.NewLine);
}
WriteToLog("Request.ContentLength: " + Request.ContentLength.ToString() + Environment.NewLine);
WriteToLog(Environment.NewLine);
}
if((Request.QueryString["configcheck"] != null) && (Request.QueryString["configcheck"] == "1"))
{
Response.Write("uploadDirectory:<br /><b>" + uploadDirectory + "</b><br />&nbsp;&nbsp;&nbsp;&nbsp;Directory.Exists:&nbsp;&nbsp;" + (System.IO.Directory.Exists(uploadDirectory)).ToString() + "<br />");
if (System.IO.Directory.Exists(uploadDirectory))
{
string sPath = uploadDirectory;
// http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/be3880f0-355e-41f6-a126-cddfd7b7a5aa
System.Security.AccessControl.DirectorySecurity DS = System.IO.Directory.GetAccessControl(sPath);
bool WriteAccess = false;
foreach (System.Security.AccessControl.FileSystemAccessRule Rule in DS.GetAccessRules(true,true,typeof(System.Security.Principal.NTAccount)))
{
if ((Rule.FileSystemRights & System.Security.AccessControl.FileSystemRights.Write) != 0)
{
WriteAccess = true;
}
}
Response.Write("&nbsp;&nbsp;&nbsp;&nbsp;WriteAccess:&nbsp;&nbsp;" + WriteAccess.ToString() + "<br /><br />");
}
Response.Write("serverPathToWebApplicationRoot:<br /><b>" + serverPathToWebApplicationRoot + "</b><br />&nbsp;&nbsp;&nbsp;&nbsp;Directory.Exists:&nbsp;&nbsp;" + (System.IO.Directory.Exists(serverPathToWebApplicationRoot)).ToString() + "<br />");
if (System.IO.Directory.Exists(serverPathToWebApplicationRoot))
{
string sPath = serverPathToWebApplicationRoot;
// http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/be3880f0-355e-41f6-a126-cddfd7b7a5aa
System.Security.AccessControl.DirectorySecurity DS = System.IO.Directory.GetAccessControl(sPath);
bool WriteAccess = false;
foreach (System.Security.AccessControl.FileSystemAccessRule Rule in DS.GetAccessRules(true,true,typeof(System.Security.Principal.NTAccount)))
{
if ((Rule.FileSystemRights & System.Security.AccessControl.FileSystemRights.Write) != 0)
{
WriteAccess = true;
}
}
Response.Write("&nbsp;&nbsp;&nbsp;&nbsp;WriteAccess (optional):&nbsp;&nbsp;" + WriteAccess.ToString() + "<br /><br />");
}
Response.Write("sLogFileFolder:<br /><b>" + sLogFileFolder + "</b><br />&nbsp;&nbsp;&nbsp;&nbsp;Directory.Exists:&nbsp;&nbsp;" + (System.IO.Directory.Exists(sLogFileFolder)).ToString() + "<br />");
if (System.IO.Directory.Exists(sLogFileFolder))
{
string sPath = sLogFileFolder;
// http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/be3880f0-355e-41f6-a126-cddfd7b7a5aa
System.Security.AccessControl.DirectorySecurity DS = System.IO.Directory.GetAccessControl(sPath);
bool WriteAccess = false;
foreach (System.Security.AccessControl.FileSystemAccessRule Rule in DS.GetAccessRules(true,true,typeof(System.Security.Principal.NTAccount)))
{
if ((Rule.FileSystemRights & System.Security.AccessControl.FileSystemRights.Write) != 0)
{
WriteAccess = true;
}
}
Response.Write("&nbsp;&nbsp;&nbsp;&nbsp;WriteAccess:&nbsp;&nbsp;" + WriteAccess.ToString() + "<br /><br />");
}
}
string[] result = handleUpload(uploadDirectory, allowedExtensions, sizeLimit, serverPathToWebApplicationRoot);
if (fLog)
{
string resultstring = string.Empty;
if(result.Length > 3) // {success:true,url:url_to_file}
resultstring = "{\"" + result[0] + "\",\"" + result[1] + "\",\"" + result[2] + "\",\"" + result[3] + "\"}";
else if(result.Length > 1)
resultstring = "{\"" + result[0] + "\",\"" + result[1] + "\"}";
WriteToLog("result: " + resultstring + Environment.NewLine);
WriteToLog(Environment.NewLine);
}
// to pass data through iframe you will need to encode all html tags
//htmlspecialchars(json_encode($result), ENT_NOQUOTES);
if(result.Length > 3) // {success:true,url:url_to_file}
Response.Write("{\"" + result[0] + "\",\"" + result[1] + "\",\"" + result[2] + "\",\"" + result[3].Replace("&","&amp;").Replace(">","&gt;").Replace("<","&lt;") + "\"}");
else if(result.Length > 1)
Response.Write("{\"" + result[0] + "\",\"" + result[1].Replace("&","&amp;").Replace(">","&gt;").Replace("<","&lt;") + "\"}");
}
// Returns array('success'=>true) or array('error'=>'error message')
public string[] handleUpload(string uploadDirectory, string[] allowedExtensions, int sizeLimit, string serverPathToWebApplicationRoot){
if (!uploadDirectory.EndsWith("\\"))
uploadDirectory = uploadDirectory + "\\";
if (System.IO.Directory.Exists(uploadDirectory))
{
string sPath = uploadDirectory;
// http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/be3880f0-355e-41f6-a126-cddfd7b7a5aa
System.Security.AccessControl.DirectorySecurity DS = System.IO.Directory.GetAccessControl(sPath);
bool WriteAccess = false;
foreach (System.Security.AccessControl.FileSystemAccessRule Rule in DS.GetAccessRules(true,true,typeof(System.Security.Principal.NTAccount)))
{
if ((Rule.FileSystemRights & System.Security.AccessControl.FileSystemRights.Write) != 0)
{
WriteAccess = true;
}
}
if(!WriteAccess) {
return new string[] {"error", "Server error. Upload directory isn't writable."};
}
int fileSize = 0;
string fileName = string.Empty;
bool fUploadHandlerXhr = false;
if (Request.QueryString["qqfile"] != null)
{
#region UploadHandlerXhr
fUploadHandlerXhr = true;
fileSize = Request.ContentLength;
fileName = Request.QueryString["qqfile"];
#endregion UploadHandlerXhr
}
else
{
#region UploadHandlerForm
if (Request.Files.Count == 0)
{
return new string[] { "error", "No files were uploaded." };
}
HttpPostedFile thisFile = Request.Files["qqfile"];
if (thisFile == null)
{
return new string[] { "error", "No files were uploaded." };
}
fileSize = thisFile.ContentLength;
fileName = thisFile.FileName;
#endregion UploadHandlerForm
}
//int fileSize = ;
if (fileSize == 0) {
return new string[] {"error", "File is empty"};
}
if (fileSize > sizeLimit) {
return new string[] {"error", "File is too large"};
}
//string pathinfo = ;
string FileName = fileName;
string Extension = System.IO.Path.GetExtension(fileName).Replace(".",string.Empty); // GetExtension includes the . in the extension: .gif
if(allowedExtensions.Length > 0)
{
// http://msdn.microsoft.com/en-us/library/bb352880.aspx only >= .net 3.5
//if(! allowedExtensions.Contains<String>(Extension))
bool fContainsExtension = false;
foreach(string str in allowedExtensions)
{
if(str == Extension)
fContainsExtension = true;
}
if(! fContainsExtension)
{
return new string[] {"error", "File has an invalid extension, it should be one of " + String.Join(",", allowedExtensions) + "."};
}
}
string sLocalPath = uploadDirectory + FileName;
if (fLog)
WriteToLog("sLocalPath:" + sLocalPath + ", File.Exists: " + (System.IO.File.Exists(sLocalPath)).ToString() + Environment.NewLine + Environment.NewLine);
if (!System.IO.File.Exists(sLocalPath))
{
if (fUploadHandlerXhr)
{
// http://forums.asp.net/p/55127/106552.aspx
FileStream newFile = new FileStream(sLocalPath, FileMode.Create); // Create a file to store the stream
byte[] body = Request.BinaryRead(Request.TotalBytes); // read the file into byte array
newFile.Write(body, 0, body.Length); // write to stream
newFile.Flush();
newFile.Close();
}
else // UploadHandlerForm
{
Request.Files["qqfile"].SaveAs(sLocalPath);
}
// ApplicationPath only returns the url after the domain name
// This replaces the server path to the web application root with the url for the application root
string URL_To_File = sLocalPath.Replace(serverPathToWebApplicationRoot, Request.Url.GetLeftPart(UriPartial.Authority) + Request.ApplicationPath).Replace("\\","/");
return new string[] { "success","true","url", URL_To_File };
} else {
return new string[] {"error", "Could not save uploaded file. The uploaded file is already on the server."};
}
} // if (System.IO.Directory.Exists(uploadDirectory))
return new string[] {"error", "Could not save uploaded file. The upload was cancelled, or server error encountered"};
}
public void WriteToLog(string message)
{
string DefaultPath = sLogFileFolder + "\\AjaxUploadLog.txt";
TextWriter output = System.IO.TextWriter.Null;
try
{
// Open log file for appending
output = File.AppendText(DefaultPath);
// Insert Entry
output.Write(message.Replace("<br />", Environment.NewLine));
}
catch { }
finally
{
// Close File
output.Close();
}
}
</script>
@SeanJA
Copy link

SeanJA commented Sep 15, 2010

Does it work if I upload a file with funny charcters in the name? ÎOâÂ¥.jpeg What about if I have a file called 2001.taxes.doc?

@Hineynu
Copy link
Author

Hineynu commented Sep 15, 2010

Hi Sean, The code will handle UTF-8 file names (I just uploaded a file with the name you posted ÎOâÂ¥.gif). I haven't tested uploading a Word doc, but I've uploaded a .zip file to test non-image binary files and it worked (I was able to open the uploaded zip file). Or was your concern a file name with two dots in it?

The only known issue is the returned json doesn't parse correctly in the browser. When I overload the onComplete event, the responseJSON is an object but not an array and I haven't been able to figure out what is wrong. I attempted to get the returned json from the hidden iframe but its innerText is empty, so I am unable to check for upload errors in the browser.

@SeanJA
Copy link

SeanJA commented Sep 15, 2010

My first concern was the two dots (just to see if I was reading the code right) apparently I was not, I misread FileName.LastIndexOf(".") as FileName.IndexOf("."). Though it does surprise me that there isn't an easier way to do it, in php we have pathinfo('/some/path/lib.inc.php') which breaks it apart nicely.

The second one I was just worried that you were cheating and using string replace instead of using a json encoding function with your latest modification (in doing this test though... I found out that the php one will fail every time because json_encode doesn't work so well with UTF8 characters and the return value for the filename is null).

The responseJSON should be an object (see here: http://www.json.org/js.html ). You should be able to do this: alert(responseJSON.success) or alert(responseJSON.error) and in your case: alert(responseJSON.url) (or console.log() if you are using chrome, safari or firefox with firebug installed).

@Hineynu
Copy link
Author

Hineynu commented Sep 15, 2010

Thank you Sean for pointing out the error with the code for getting a file extension. There was a bug in my code (it added 1 to the LastIndexOf return value, then checked if it was > -1 and not > 0), and I took your suggestion to look into the .NET documentation and found System.IO.Path.GetExtension! I changed the code to use that.

You're right that I'm not encoding the json as I should. .net handles UTF-8 very well but did not add json encoding until .net 3.5 and I'm running on .net 2.0. I probably should use the code at http://www.west-wind.com/weblog/posts/114530.aspx and will add it when I am able.

@SasSam
Copy link

SasSam commented Nov 25, 2010

An idea for "max file size" section:
// max file size in bytes
// Get the official size limit from Server
int sizeLimit = Convert.ToInt32(ConfigurationManager.OpenMachineConfiguration().SectionGroups["system.web"].Sections["httpRuntime"].ElementInformation.Properties["maxRequestLength"].Value) * 1024;

  // Try to get the custom settings from web.config
  HttpRuntimeSection section = ConfigurationManager.GetSection("system.web/httpRuntime") as HttpRuntimeSection;
  if (section != null)
  {
    sizeLimit = section.MaxRequestLength * 1024;
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment