• Jpg文件的Mimetype为Image/Jpeg

    by{ guangboo }, published {2010-03-25}, Tag { HTML / .net / }

    由于项目的原因,开发了几套系统,部署在不同的服务器上,但数据库可以统一的访问,但附件就不太那么容易处理了,如文章里面的图片一般都是存储在磁盘上的,并且都是相对路径,而其他系统访问此文章的时候,图片就获取不到了。

    这里的解决方案是使用DFS,分布式文件服务系统,将文件共享,或可以利用DFS复制,同步这些图片。因为DFS复制需要使用域和AD的方式来创建文件根目录,我使用的是独立根目录创建的,因此访问图片还是要共享的服务器上读取。

    图片的读取时没有问题的,但在IE 6下,文章中显示图片没有问题,但使用IE 6直接访问图片就不行了,在IE 8下面文章中显示图片和直接访问图片都不能显示。后来发现,bmp格式的图片都能访问,无论在IE 6还是IE 8,还是在文章中显示,还是直接访问图片都正常。偏偏是jpg格式的文件出现上述情况。

    原来我去图片的MimeType的时候出的问题,因为,bmp,gif等的MimeType为image/bmp,image/gif,而jpg的MimeType是image/jpeg,因此简单的使用"image/" + extesion,是可靠的。

  • Asp.Net Datacontrolrowstate简介

    by{ guangboo }, published {2010-03-24}, Tag { .net / asp.net / }

    DataControlRowState 枚举

    该枚举在.net framework 2.0中新增加的,是指定数据控件,如DetailView,GridView中行的状态的。具有FlagAttribute属性,因此允许其成员值按位组合。

     

    [FlagsAttribute] 
    public enum DataControlRowState

    成员

    成员名称 说明
    Alternate 指示该数据控件行是交替行。 Alternate 状态在任何时候都可以与其他状态组合,例如与 NormalEditInsert 组合。这些行可能会受到数据控件的 AlternateRowStyle 属性影响(若已设置)。
    Edit 指示该行处于编辑状态,这通常是单击行的“编辑”按钮的结果。通常,EditInsert 状态互相排斥。
    Insert 指示该行是新行,这通常是单击“插入”按钮添加新行的结果。通常,InsertEdit 状态互相排斥。
    Normal 指示该数据控件行处于正常状态。Normal 状态与其他所有状态互相排斥。
    Selected 指示该行已被用户选定。

    官方介绍

    DataControlRowState 枚举标识数据控件(例如 DetailsViewGridView)中行的状态。行的状态可以是一个 DataControlRowState 值或值的组合,因此使用按位运算来确定该行的状态是否包括一个 DataControlRowState 值而非一个等效测试。DataControlRowState 枚举用于任何行类型,而不只用于 DataRow 行(通常,标头和脚注行的状态设置为 Normal)。

    当枚举整个 GridViewRowCollectionDetailsViewRowCollection 集合时,可以使用 DataControlRowState 枚举来分别标识 GridViewRowDetailsViewRow 对象的状态。如果正在编写使用行的数据控件,您可以使用 DataControlRowState 枚举来标识何时为行呈现不同的颜色(Alternate 值),或者用它来标识为编辑行而启用或禁用的控件(EditInsert 值)。

    示例:

    判断行在Edit模式

    (row.RowState & DataControlRowState.Edit) != 0

    而不能使用

    row.RowState == DataControlRowState.Edit

    判断行在Insert模式

    (row.RowState & DataControlRowState.Insert) != 0
    而不能使用
    row.RowState == DataControlRowState.Insert

    因为DataControlRowState的声明是:

    [Flags]
        public enum DataControlRowState {
            // 摘要:
            //     指示该数据控件行处于正常状态。System.Web.UI.WebControls.DataControlRowState.Normal 状态与其他状态相互排斥,但
            //     System.Web.UI.WebControls.DataControlRowState.Alternate 状态除外。
            Normal = 0,
            //
            // 摘要:
            //     指示该数据控件行是交替行。
            Alternate = 1,
            //
            // 摘要:
            //     指示该行已被用户选定。
            Selected = 2,
            //
            // 摘要:
            //     指示该行处于编辑状态,这通常是单击行的“编辑”按钮的结果。通常,System.Web.UI.WebControls.DataControlRowState.Edit
            //     和 System.Web.UI.WebControls.DataControlRowState.Insert 状态互相排斥。
            Edit = 4,
            //
            // 摘要:
            //     指示该行是新行,这通常是单击“插入”按钮添加新行的结果。通常,System.Web.UI.WebControls.DataControlRowState.Insert
            //     和 System.Web.UI.WebControls.DataControlRowState.Edit 状态互相排斥。
            Insert = 8,
        }

  • Response.Redirect 产生的“正在中止线程”错误

    by{ guangboo }, published {2010-02-26}, Tag { .net / asp.net / }

    Response.Redirect 产生的“正在中止线程”错误 
    这两天在开发调试过程中,老是会出现在一个 
    "正在中止线程 “(ThreadAbortException)的例外信息。
    例外是 由 Response.Redirect 方法产生的,虽然知道是线程的问题, 但是不知为何 Redirect会出现这样的错误,以前是没有碰到过,转 移到 Asp.net 2.0 开发就遇上了。
    在狂Google了一下后,才发现MS早就发现了这个问题,但提供了解决方法。以下是主要信息的摘要:
    症状
    如果使用 Response.End、Response.Redirect 或 Server.Transfer 方法,将出 现 ThreadAbortException 异常。您可以使用 
    try-catch 语句捕获此异常。 
    原因
    Response.End 方法终止页的执行,并将此执行切换到应用程序的事件管线中 的 Application_EndRequest 事件。不执行 Response.End 后面的代码行。

    此问题出现在 Response.Redirect 和 Server.Transfer 方法中,因为这两种方法均在内部调 用 Response.End。 
    解决方案
    要解决此问题,请使用下列方法之一:• 对于 Response.End,调 用 HttpContext.Current.ApplicationInstance.CompleteRequest 方法而不 是 Response.End 以跳过 Application_EndRequest 事件的代码执行。 
    • 对于 Response.Redirect,请使用重载 Response.Redirect(String url, 
    bool endResponse),该重载对 endResponse 参数传递 false 以取消 对 Response.End 的内部调用。例如: Response.Redirect ("nextpage.aspx"false);

    摘自:http://www.cnblogs.com/wenanry/archive/2007/07/12/815271.html

  • C#创建临时文件

    by{ guangboo }, published {2009-12-08}, Tag { CSharp / .net / asp.net / }

    在使用C1.C1Excel控件将DataTable导出到Excel表格的时候,遇到一个问题。原来的代码是:

    C1XLBook book = ExcelDocument.Instance.ExpertExcel(dt);
    string fileName = Path.GetFileNameWithoutExtension(TMP_PATH + "\\" + dt.TableName) + ".xls";
    book.Save(fileName);
    book.Dispose();
    FileStream fs = null;
    try {
        fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
        byte[] buffer = new byte[(int)fs.Length];
        fs.Read(buffer, 0, buffer.Length);
        
        Response.ContentEncoding = Encoding.GetEncoding("GB2312");
        Response.HeaderEncoding = Encoding.GetEncoding("GB2312");
        Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(Path.GetFileNameWithoutExtension(fileName)) + ".xls");
        Response.AppendHeader("Content-Length", buffer.Length.ToString());
        Response.ContentType = "application/octet-stream";
        Response.OutputStream.Write(buffer, 0, buffer.Length);
    }finally{
    	fs.Close();
        try{
        	File.Delete(fileName);
        }catch{}
    }
    

    上面的代码中fileName的值为Path.GetFileNameWithoutExtension(TMP_PATH + "\\" + dt.TableName) + ".xls",其中TMP_PATH是Web.config里面配置的,使用ConfigurationManager.AppSettings[""]获取的,fileName="E:\TMP\****.xls"。

    我其实也没有在E盘下创建TMP文件夹,跟没有给该文件夹添加任何的权限,但是我在使用VS自带的服务器运行网站的时候,完全没有问题,奇怪的是,我在将数据导出到Excel的过程中,一直观察E盘,就是没有发现TMP文件,也没有错误信息,也许是我刷新的不够快吧。

    但到我不网站部署到测试服务器的时候,运行导出程序就出现问题了“System.IO.IOExcetpion:Failed to create storage file.”,问题就出在book.Save(fileName)上,立即想到的是没有给这个TMP_PATH文件夹足够的权限,但是设了半天,问题还是一样。

    然后使用reflector工具,查看C1.C1Excel的源码,根据异常堆栈提供的错误信息,找到C1XLBook的Save(fileName)方法:

    public void Save(string fileName)
    {
        string str;
        bool flag = false;
        if (((str = Path.GetExtension(fileName).ToLower()) != null) && ((str == ".xlsx") || (str == ".zip")))
        {
        	flag = true;
        }
        this.o(fileName, flag);
    }
    

    该方法执行到this.o(fileName, flag)的时候出现异常,然后我又跟踪到o方法:

    internal void o(string A_0, bool A_1)
    {
        if (this.Sheets.Count == 0)
        {
        	n("Cannot save empty book (need at least one sheet).", true);
        }
        bool flag = false;
        foreach (XLSheet sheet in (IEnumerable) this.Sheets)
        {
            if (sheet.Visible)
            {
                flag = true;
                break;
            }
        }
        if (!flag)
        {
        	n("Cannot save book without any visible sheets.", true);
        }
        this.f();
        using (au au = au.a(A_0))
        {
        	using (cg cg = au.c("Workbook"))
            {
            	this.q(cg);
            }
        }
        this.e();
    }
    

    继续向上跟踪,到在using (au au = au.a(A_0))语句的时候出现了异常,然后定位到au类的a方法:

    internal static au a(string A_0)
    {
        int num = 0x1012;
        bg bg = null;
        if ((StgCreateDocfile(A_0, num, 0, out bg) != 0) || (bg == null))
        {
        	throw new IOException(l.e("Failed to create storage file."));
        }
        return new au(bg);
    }
    

    很显然IOException(l.e("Failed to create storage file."))异常被抛出了,然后我又定位到StgCreateDocfile方法:

    [DllImport("OLE32.DLL")]
    private static extern int StgCreateDocfile([MarshalAs(UnmanagedType.LPWStr)] string A_0, int A_1, int A_2, out bg A_3);
    

    该方法是来说OLE32.DLL文件,此时我马上想到也行测试服务器上没有ole32.dll文件,后来我在windows/system32/下面找到ole32.dll文件,虽然文件大小和版本和我的win7上的不一样,但是问题应该不在这里,而且无也不敢随便将这个文件替换,怕影响了sql和其他程序的运行。

    然后我就开始在google上搜寻答案,其中有一个答案最有可能:

      >>>>>>>>>>>>>
      IIS requires file/directory permissions to be set so that the anonymous 
      users have write access to the directory.
      
      IUSR_, IWAM_
      
      By file permissions, I mean the permissions you would set using Windows 
      Explorer file/directory Properties - Security tab. You can also set these 
      using cacls.exe from Run or a command line. Setting them from code is nasty, 
      with all kinds of objects involved. It's so nasty, that even MS 
      installations tend to use calcs.exe from a system or spawn call (that's the 
      little Dos box you see pop up and go away during some installations).
      
      It is also necessary to allow write permission on the Virtual directory - 
      Virtual Directory tab of IIS Website directory properties. Note, that in a 
      live situation, both Write and Execute (scripts or executables) should NOT 
      be granted together. You don't want people writing things that execute.
      
      >>>>>>>>>>>>>
      
      I did write a sample to check this. Here's what my code looks like:
      
      private void Button1_Click(object sender, System.EventArgs e)
      {
          this.c1XLBook1.Clear();
          C1.C1Excel.XLSheet sheet = this.c1XLBook1.Sheets[0];
          sheet[0,0].Value = "Hello from ASP.NET";
          string xlsFile = @"temp\hello.xls";
          this.c1XLBook1.Save(Page.MapPath(xlsFile)); // << map to absolute path
          this.Response.Redirect(xlsFile);
      }
      
      When I ran this, I got the error you described. That was to be expected, 
      since I didn't create or set permissions on the "temp2" folder. Then I did 
      this:
      1) Open the IIS management console, look for the application's virtual 
      directory, right-click, select "New | Virtual Directory".
      2) Type in the alias ("temp") and select the path for the new virtual 
      directory. (Navigate to the app folder, click the "Make New Folder" button, 
      and type "temp" to create the new temp folder).
      3) In the "Access Permissions" step, select "Read" and "Write" (make sure 
      "Run" and "Execute" are not checked).
      
      This takes care of the IIS side of the story. If you run the app now, you 
      will get the same error though. That's because the folder permissions are 
      not set yet. To set the folder permissions, right-click the new folder in 
      the Windows Explorer, select "Sharing and Security...", then pick the 
      "Security" tab.
      
      This is where things get complicated, because you must grant permissions 
      based on how your accounts are set up, and this depends on which OS/IIS/.NET 
      combination you have.
      
      The simplest thing to do (on your development machine) is delete all groups 
      except two: "Administrators" and "Everyone". Members of the "Administrators"
      group should be allowed to do everything. Members of the "Everyone" group 
      should be allowed to "Read" and "Write" (but not execute, list folder 
      contents, etc). To delete the groups, you will probably have to click the 
      "Advanced" button and uncheck the "Inherit" checkbox.
      
      Attached is a screenshot of the Security Properties dialog after this is all 
      setup. After making these changes, my sample web app works fine. The xls 
      files are created under the temp folder and I can redirect the browser to 
      them.
      
      I hope this information helps.
      
      Please note that this is an easy way to set up the securities on your 
      development environment. On production systems, the sysadmin would probably 
      be more restrictive and grant permissions to specific users instead of 
      "Everyone". But since we're not granting execute permissions anyway, this 
      seems OK at least for debugging environments. If anyone has additional 
      information on this topic, please feel free to share it.
    

    这段EN文,大概的意思就是在目录文件IIS运行用户的权限,我觉得很麻烦,然后就试着不要自己手动添加临时文件夹,而采用系统自己的临时文件夹,使用System.IO.Path.GetTempFileName()可以创建一个临时文件,如:C:\Users\Jeff\AppData\Local\Temp\tmpEAFD.tmp,这是我的Win7下的临时文件,也行你的XP是:C:\Documents and Settings\UserName\Local Settings\Temp\tmpEAFD.tmp。而且你也可以使用File.Delete来删除该临时文件。
    修改后的代码为:

    C1XLBook book = ExcelDocument.Instance.ExpertExcel(dt);
    string fileName = Path.GetTempFileName();
    book.Save(fileName);
    book.Dispose();
    FileStream fs = null;
    
    try {
        fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
        byte[] buffer = new byte[(int)fs.Length];
        fs.Read(buffer, 0, buffer.Length);
        
        Response.ContentEncoding = Encoding.GetEncoding("GB2312");
        Response.HeaderEncoding = Encoding.GetEncoding("GB2312");
        Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(Path.GetFileNameWithoutExtension(fileName)) + ".xls");
        Response.AppendHeader("Content-Length", buffer.Length.ToString());
        Response.ContentType = "application/octet-stream";
        Response.OutputStream.Write(buffer, 0, buffer.Length);
    } catch(Exception ex) {
        lblResult.Text = "生成Excel文件过程中,出现异常:" + ex.Source;
        lblResult.Visible = true;
    } finally {
        fs.Close();
        try {
        	File.Delete(fileName);
        } catch { }
    }
    
  • Vs2008与Iis 7.0使用在Windows 7上时出现Internet Explorer 无法显示该页面

    by{ guangboo }, published {2009-09-22}, Tag { .net / asp.net / }

    装Windows 7,也装了VS 2008,一直没有使用vs,今天出差回到公司后,发现运行东北证券的项目时出现“Internet Explorer cannot display the webpage”的错误,但是使用New site创建网站是可以正常运行的,但是创建C# Project-》ASP.net web application就不能运行了,就出现上面的错误。装了 IIS7 也不行。

    后来在网上找到解决方法:

    使用记事本打开:c:\windows\system32\drivers\etc\hosts

    将最好两行是:

    # 127.0.0.1        localhost

    # ::1                localhost

    呵呵,原来是DNS的问题,将注释去掉。OK!

    注意保留# ::1                localhost的注释,该段表示localhost的IPV6地址。

  • 访问Iis元数据失败

    by{ guangboo }, published {2009-09-17}, Tag { .net / asp.net / visual studio / }

    刚才帮朋友在其XP机器上不少采编系统,结果出现"访问IIS元数据失败"的错误,检查IIS下该虚拟目录的属性,在ASP.NET选项下有v2.0..。但是是奇怪的时候该机器装的是VS 2008,应该会有2.0,3.0,3.5的啊。

    使用VS 2008把项目打开,编译,可以使用VS 自带的ASP.NET SERVER运行系统;

    发布一份在IIS上新建一个虚拟目录访问该系统还是“访问IIS元数据失败”。

    在网上搜罗了一下,该问题的解决方法很多,摘取了一个,如下:

    在在命令行下,到C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\目录,运行aspnet_regiis.exe -i。则会提示安装.net v2.0.50727,稍等几分钟,安装成功!

    运行OK!

    出现该问题的原因是可能先装的VS 2008,而后装的IIS。