图片及文件上传和下载[转]

本文简单介绍ASP.NET 2.0中将图片或文件上传到服务器或保存到数据库的方法,以及保存后如何显示和下载。
1.图片及文件保存到服务器
1.1 上传
本示例构造一个能将文件上传到服务器指定目录的页面。
(1)       新建一个ASP.NET网站,增加web.config配置文件。
(2)       在解决方案资源管理器中,在网站名称上单击鼠标右键,增加一个文件夹,取名为Images,作为上传文件的路径。
(3)       进入default.aspx的设计模式,从工具箱的标准选项卡中,拖一个FileUpload控件到页面上,默认ID为“FileUpload1”。该控件负责选中一个文件。
(4)       拖一个Button到页面上,Text属性设置为“上传”,ID设置为btnUpload。点击该按钮后,上传文件。
(5)       为上传按钮增加Click事件。
(6)       在Click事件中,增加以下代码:
    protected void btnUpload_Click(object sender, EventArgs e)
    {
        // 是否选中了文件,如果没有选中,提示并返回
        if (FileUpload1.FileName == "")
        {
            Response.Write("<script language='javascript'>alert('请先选中一个文件再点击上传按钮!');</script>");
            return;
        }
 
        /* 为防止上传的文件重名,将上传时间追加到文件名之后
         * 获取新文件名开始     */
 
        // 取得上传文件名,注意这样得到的是完整路径+文件名
        string strFileName = FileUpload1.FileName;
 
        // 得到最后一个“\”的位置
        int nIndex = strFileName.LastIndexOf('\\');
 
        // 得到真正的文件名
        strFileName = strFileName.Substring(nIndex + 1);
 
        // 得到文件后缀前的“.”所在位置
        nIndex = strFileName.LastIndexOf('.');
 
        // 将“文件名.后缀”改为“文件名+时间.后缀”(那个加号表示连接)
        strFileName = strFileName.Substring(0, nIndex)
+ DateTime.Now.ToString("yyyyMMddHHmmss")
+ strFileName.Substring(nIndex);
        /* 获取新文件名结束 */
 
        // 将上传文件的虚拟目录映射为服务器绝对路径
        string strPath = Server.MapPath("./Images/" + strFileName);
 
        // 上传文件
        FileUpload1.PostedFile.SaveAs(strPath);
}
(7)       运行,选中一个文件并上传,看一下是否上传到了Images目录。如果不选中文件直接点上传,看是否有提示。
1.2 文件的使用
上传文件的目的是为了使用它,一般在上传文件过程中,我们把新的文件名记入数据库。在使用时,可以用超级连接<a href=’./Images/新文件名’>显示文本</a>。点击这个超级链接,如果是图片,则会直接打开;如果是文件,则会弹出一个对话框,提示是保存还是直接打开。
如果上传的是图片,要把它嵌入到网页的固定位置,可以使用<img src=’./Images/新文件名’ />标签或使用Image控件。
1.3 优缺点
文件保存到服务器的优点是使用比较简单。缺点是,如果要删除一个文件,必须在Images上创建一个可写的虚拟目录,或者直接将发表的虚拟目录设置为可写的。
将虚拟目录设置为可写的有严重的安全缺陷,因为任何人都可以写这个虚拟目录,无法杜绝别有用心的人写入一个恶意文件。因此一般服务器不允许建立可写虚拟目录,这样删除文件就受到限制。
删除文件可以使用FileInfo类,可以自己写一下删除文件的代码,看一下没有建立可写虚拟目录时删除是否可以,然后创建可写虚拟目录再试一下。
2.图片及文件保存到数据库
此例我们以图片为例,对文件操作也是类似的。
2.1 上传
(1)            在DbTemp数据库中,创建一个名为UpFiles的表,用来存放上传的图片,字段如下:
字段名
意义
数据类型
备注
FileID
文件ID
int
设为字段增长、主键
FileName
文件名
Varchar(50)
 
FileContent
上传文件的内容
Image
 
 
(2)            添加一个Web窗体,名为Default2.aspx。
(3)            进入页面的设计模式,拖入一个FileUpload。
(4)            拖入一个Button,Text设为“上传”,ID为“btnUpload”。
(5)            拖入一个GridView,用于显示文件名。
(6)            的数据源选择“新建数据源”,弹出新建数据源向导。GridView
(7)            数据源类型选择为“数据库”,名字为SqlFileSource,确定。
(8)            新建一个数据库连接,如果忘记了怎么做,可以参考blog中《ASP.NET2.0入门(1)——访问数据库》那篇文章。
(9)            在配制Sql语句界面,选择“指定自定义SQL语句或存储过程”,然后选择“下一步”。
(10)        语句设置为“SELECT FileID, FileName, FileContent FROM UpFiles ORDER BY FileID”。Select
(11)        语句设置为“INSERT INTO UpFiles(FileName, FileContent) VALUES (@FileName, @FileContent)”。Insert
(12)        语句设置为“DELETE FROM UpFiles WHERE (FileID = @original_FileID)”。Delete
(13)        完成数据源的创建,并启用删除。
(14)        将SqlFileSource的OldValuesParameterFormatString属性设置为“original_{0}”。
(15)        点击InsertQuery属性后的按钮,选中参数FileContent,将参数源设置为Control,ControlID设置为FileUpload1,确定。
(16)        经过设置后,aspx的body内代码如下:
<body>
    <form id="form1" runat="server">
    <div>
        <asp:FileUpload ID="FileUpload1" runat="server" Width="338px" />
        <asp:Button ID="btnUpload" runat="server" Text="上传" />
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="FileID"
            DataSourceID="SqlFileSource">
            <Columns>
                <asp:CommandField ShowDeleteButton="True" />
                <asp:BoundField DataField="FileID" HeaderText="FileID" InsertVisible="False" ReadOnly="True"
                    SortExpression="FileID" />
                <asp:BoundField DataField="FileName" HeaderText="FileName" SortExpression="FileName" />
            </Columns>
        </asp:GridView>
        <asp:SqlDataSource ID="SqlFileSource" runat="server" ConnectionString="<%$ ConnectionStrings:DbTempConnectionString %>"
            DeleteCommand="DELETE FROM UpFiles WHERE (FileID = @original_FileID)" InsertCommand="INSERT INTO UpFiles(FileName, FileContent) VALUES (@FileName, @FileContent)"
            OldValuesParameterFormatString="original_{0}" SelectCommand="SELECT FileID, FileName, FileContent FROM UpFiles ORDER BY FileID">
            <DeleteParameters>
                <asp:Parameter Name="original_FileID" />
            </DeleteParameters>
            <InsertParameters>
                <asp:Parameter Name="FileName" />
                <asp:ControlParameter ControlID="FileUpload1" Name="FileContent" PropertyName="FileBytes" />
            </InsertParameters>
        </asp:SqlDataSource>
    </div>
    </form>
</body>
(17)        为上传按钮增加Click事件:
    protected void btnUpload_Click(object sender, EventArgs e)
    {
        // 是否选中了文件,如果没有选中,提示并返回
        if (FileUpload1.FileName == "")
        {
            Response.Write("<script language='javascript'>alert('请先选中一个文件再点击上传按钮!');</script>");
            return;
        }
 
        // 取得上传文件名,注意这样得到的是完整路径+文件名
        string strFileName = FileUpload1.FileName;
 
        // 得到最后一个“\”的位置
        int nIndex = strFileName.LastIndexOf('\\');
 
        // 得到真正的文件名
        strFileName = strFileName.Substring(nIndex + 1);
 
        // 插入数据
        SqlFileSource.InsertParameters["FileName"].DefaultValue = strFileName;
        SqlFileSource.Insert();
}
(18)        运行程序,选择一个图片上传,可以看到列表中的显示。删除一个图片,可以看到能直接删除。
2.2 图片的显示
图片放到数据库后,显示有一些问题,因为我们没有办法直接用src或ImageUrl之类的属性去请求它。但我们回顾一下blog中《Web绘图(1)——服务器端绘图》那篇文章,就可以找到方法,那就是用一个aspx页面将图片取出并保存,把这个aspx页面转换为图片数据。
现在我们要在那个GridView中显示文件名那一列做个超级链接,点击超级链接显示图片,过程如下:
(1)           在解决方案资源管理器的网站名称上单击鼠标右键,选择“添加ASP.NET文件夹”菜单下的“App_Code”,创建一个App_Code文件夹。我们写的不在aspx页面下的代码,以及创建的数据集等都必须放到这个文件夹下(微软有时候为了自己方便也是瞎搞),我们将在这个文件夹下创建一个类型化数据集,用来读取文件内容。
(2)           在新建的“App_Code”文件夹上,单击鼠标右键,选择“添加新项”菜单。
(3)           弹出的对话框中,选择“数据集”,名字取为“FileSet.xsd”,选择“添加”按钮,这时候弹出“TableAdapter配制向导”。(一个数据集中可以放多个表,添加第二个表时可以从工具箱中拖个TableAdapter过来,剩下的和下面的方法就一样了)。
(4)           向导第一步是建立连接字符串,因为我们前面已经建立了一个,就不用新建了,直接选择那个就可以了。
(5)           下一步是选择命令类型,我们选择“使用SQL语句”,再下一步。
(6)           语句输入“SELECT FileID, FileName, FileContent FROM UpFiles WHERE (FileID = @FileID)”。SQL
(7)           一直下一步到完成,这样就建立的一个数据集,而且我们还可以看到里面有个UpFiles表,对应的就是数据库中的表。表下面有个UpFilesTableAdapter,这个适配器中自动生成了从数据库读取数据的Fill代码,以及修改数据库的Update代码等(微软这方面考虑真实周全,所有代码都替我们写好了)。
(8)           创建一个名为“ImageShow.aspx”的Web窗体,我们将在这个窗体中读出数据库中的数据,并保存为图片。
(9)           在该窗体的Page_Load事件中,输入如下代码:
    protected void Page_Load(object sender, EventArgs e)
    {
        // 创建数据集实例
        FileSet fileSet = new FileSet();
 
        // 创建数据适配器实例
        FileSetTableAdapters.UpFilesTableAdapter adapter = new FileSetTableAdapters.UpFilesTableAdapter();
 
        // 读取数据,我们从GridView通过QueryString方式传入参数FileID,该参数是数据库中记录的文件ID
        adapter.Fill(fileSet.UpFiles, int.Parse(Request["FileID"]));
 
        // 取出二进制文件内容,假设文件一定存在,则第0行的FileContent字段就是我们要取的数据
        byte[] by = (byte [])fileSet.UpFiles.Rows[0]["FileContent"];
 
        // 写入输出流
        Response.BinaryWrite(by);
}
(10)       回到Default2.aspx的设计模式,前面GridView中我们显示的是文件名,下面改成超级链接显示。
(11)       选中GridView,点击Columns属性后面的按钮,弹出显示的字段对话框。
(12)       将“选定的字段”列表框中的FileName字段删除。
(13)       在“可用字段”列表框中选择“HypeLinkField”,加入到“选定的字段”列表框。
(14)       选中新增的那个“HypeLinkField”,修改如下属性:
属性名
注释
DataNavigateUrlFields
FileID
绑定的Url字段
DataNavigateUrlFormatString
ImageShow.aspx?FileID={0}
Url格式,传递FileID参数到ImageShow.aspx
DataTextField
FileName
显示的字段
HeaderText
文件名称
GridView该列的表头
Target
_blank
点超级链接后弹出一个新窗口显示图片
 
(15)       确定后运行,看一下效果。超级链接列显示的是文件名字,点击超级链接,会弹出一个新窗口(可不用让你的防火墙拦截噢),新窗口中显示的是我们上传的图片。
2.3 优缺点
优点比较明显,就是删除比较容易,删除那条记录就可以了,没有了可写虚拟目录的安全隐忧。
缺点也比较明显,就是麻烦。
3.关于文件批量上传
有很多人询问或企图寻找一个实现文件批量上传的途径,就是能把一批文件一次上传,而不用一个一个选择。如果你真正理解了互联网,就不会再有这种想法了。
想象一下吧,如果真的有一款浏览器能实现批量文件上传,就可以写一个网站,只要别人浏览你的网站,就可以把别人硬盘上的文件都读入到你的服务器上去,别人所有的秘密就都暴露到你的眼前了,这可是个不可原谅的安全问题。
实际上,浏览器想实现文件批量上传,技术上没有难度,但这款浏览器肯定没有市场,没人敢用它。ActiveX很容易能实现这个功能,这也是ActiveX的安全性广受诟病的一个原因。
忘掉文件批量上传吧,Web程序只能选择一个文件,上传一个。要想同时上传n个文件,就要在页面上放置n个FileUpload。
posted @ 2007-07-25 09:58  星空竹月  阅读(1788)  评论(1编辑  收藏  举报