但用户键入相关的类别信息,点Insert按钮后,发生页面回传,接着发生一连串的插入流程。首先,DetailsView控件的ItemInserting event事件发生;接着,调用ObjectDataSource控件的Insert()方法,它将导致Categories表添加新记录;最后,发生DetailsView控件的ItemInserted event事件。
在调用ObjectDataSource控件的Insert()方法以前,我们必须确保用户已经上传了恰当的文件并保存在服务器的文件系统。为此,我们为DetailsView控件的ItemInserting事件创建一个事件处理器,添加如下的代码:
// Reference the FileUpload control FileUpload BrochureUpload = (FileUpload)NewCategory.FindControl("BrochureUpload"); if (BrochureUpload.HasFile) { // Make sure that a PDF has been uploaded if (string.Compare(System.IO.Path.GetExtension (BrochureUpload.FileName), ".pdf", true) != 0) { UploadWarning.Text = "Only PDF documents may be used for a category's brochure."; UploadWarning.Visible = true; e.Cancel = true; return; } }
代码首先引用DetailsView控件模板里名为BrochureUpload的FileUpload控件,如果已经上传了文件,就检查FileUpload控件的extension是否为“.PDF”, 如果不是则取消插入操作并退出。
注意:通过检查文件的扩展名(extension)来确保用户上传的为PDF文件的做法并不是万全之策。比如,可能用户的确上传的是PDF文件,只不过其扩展名为.Brochure;或者用户提供的并不是PDF文件,却使用.pdf的扩展名。保险的做法是通过编程对文件内容做最后一次检查。如此一来,虽然彻底,但稍嫌过头(overkill)。在绝大多数情况下,检查文件扩展名就已经足够了。
就像在教程《使用FileUpload上传文件》里讨论的那样,将文件保存在文件系统里时要特别小心,以免覆盖别人上传的文件。本节,我们尝试对上传文件使用一个已经使用的名字,在名字末尾添加一个数字,以示区别。举例,如果在文件夹~/Brochures里存在一个名为Meats.pdf的文件,上传文件时我们取名为Meats-1.pdf,如果文件夹里恰好也存在一个Meats-1.pdf文件,我们就取名为Meats-2.pdf,以此类推,直到文件名唯一为止。
下面的代码使用File.Exists(path)方法来判断是否已经存在同名文件,如果存在,就重新命名,直到名字唯一为止:
const string BrochureDirectory = "~/Brochures/"; string brochurePath = BrochureDirectory + BrochureUpload.FileName; string fileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(BrochureUpload.FileName); int iteration = 1; while (System.IO.File.Exists(Server.MapPath(brochurePath))) { brochurePath = string.Concat(BrochureDirectory, fileNameWithoutExtension, "-", iteration, ".pdf"); iteration++; }
一旦找到唯一的文件名后,立即将文件保存在文件系统,同时更新ObjectDataSource控件的InsertParameter参数brochurePath的值,以便将文件名写入数据库。就像在教程《使用FileUpload上传文件》里看到的一样,可以使用FileUpload控件的SaveAs(path)方法来保存文件。使用e.Values集合来更新ObjectDataSource控件的参数brochurePath。
// Save the file to disk and set the value of the brochurePath parameter BrochureUpload.SaveAs(Server.MapPath(brochurePath)); e.Values["brochurePath"] = brochurePath;
第7步:将上传的图片保存到数据库
为了把上传的图片保存在新添加的记录里,我们需要在DetailsView控件的ItemInserting事件里,用上传的数据对ObjectDataSource控件的picture参数赋值。然而,在此之前,我们需要确保上传的文件为JPG而不是其它的什么格式。就象在第6步中探讨的一样,我们用文件的扩展名来检查其类型。
虽然Categories表允许Picture列为NULL值,但所有的种类都应该有一张图片。在本页面,我们强制用户添加记录时提供图片。下面的代码确保已经上传图片,且为恰当的类型。
// Reference the FileUpload controls FileUpload PictureUpload = (FileUpload)NewCategory.FindControl("PictureUpload"); if (PictureUpload.HasFile) { // Make sure that a JPG has been uploaded if (string.Compare(System.IO.Path.GetExtension(PictureUpload.FileName), ".jpg", true) != 0 && string.Compare(System.IO.Path.GetExtension(PictureUpload.FileName), ".jpeg", true) != 0) { UploadWarning.Text = "Only JPG documents may be used for a category's picture."; UploadWarning.Visible = true; e.Cancel = true; return; } } else { // No picture uploaded! UploadWarning.Text = "You must provide a picture for the new category."; UploadWarning.Visible = true; e.Cancel = true; return; }
这些代码应放在第6步中的代码前面,如果上传的文件有问题,事件处理器在文件保存到文件系统前就结束了。
假设上传的文件没有问题,然后我们用下面的代码将上传文件的数据分配给参数picture:
// Set the value of the picture parameter e.Values["picture"] = PictureUpload.FileBytes;
完整的ItemInserting事件处理器
下面是ItemInserting事件处理器的完整代码: