一、這篇文章主要是要實現:圖片新聞的添加,無刷新圖片的上傳,以及添加新聞靜態頁的生成。
-
- 無刷新圖片的上傳用到的組件:jquery.uploadify.js、uploadify.swf、uploadify.css。
- 文本編輯器:ckeditor、ckfinder。
- 前台圖片無縫滾動:jquery.switchable[all].min.js,前一篇有介紹。
- 靜態頁的生成:其實有多種方式,最常見的:(1)WebClient中有個方法,下載Html到本地。(2)StreamWriter,以流的方式輸出。這里 介紹第二種,StreamWriter。
- 靜態頁生成分頁(補充):由於有些文章篇幅過長,就得使用到分頁。提示:Ckediter中有個分頁按鈕(但是得在代碼中正則匹配)。
- 制作靜態頁思路:首先預先定義一個.html模版,然后StreamReader讀取,Replace掉要換的地方(如:標題,日期,內容.....),接着StreamWriter到本地。


添加完之后前台顯示滾動圖片:如下圖

添加完新聞之后生成的靜態頁:如下圖

由於篇幅過長:添加完新聞之后生成的“分頁”靜態頁:如下圖:

二、實現上面“圖片新聞添加”的功能:
-
- 添加HomeController,添加AddImage Action。
-
方法上添加[ValidateInput(false)]該值指示是否啟用驗證。 -
HttpPostedFileBase[] photo,表示前台傳入name為上傳的文件。其中(ContentLength:獲取上傳文件的大小,ContentType:獲取上傳文件的 MIME 內容類型,FileName:上傳的文件名,SaveAs:保存上載文件的內容)
- 接着判斷上傳的內容進行判斷是否為空,進行校驗,當然在前台使用Jquery.也可以(推薦使用),因為MVC中本身提供了校驗,MicrosoftAjax.js、MicrosoftMvcAjax.js、MicrosoftMvcValidation.js。結合Model屬性的ComponentModel。
- XElement,我這個項目使用的XML保存圖片的信息(最重要:圖片的路徑),所以使用.Load()來加載我的XML,使用SetElementValue設置圖片的信息。
public ActionResult AddImage() { return this.View(); } [HttpPost] [ValidateInput(false)] [AcceptVerbs(HttpVerbs.Post)] public ActionResult AddImage(FormCollection collection, string filepath, int? filesize, HttpPostedFileBase[] photo) { HomeImage hHomeImage = new HomeImage(); TryUpdateModel(hHomeImage, collection); hHomeImage.ImgUrl = filepath; if (hHomeImage.Name.IsNullOrEmpty()) { return View("AddImage", hHomeImage); } if (hHomeImage.Content.IsNullOrEmpty()) { return View("AddImage", hHomeImage); } if (filepath.IsNullOrEmpty() && hHomeImage.ImgUrl.IsNullOrEmpty()) { return View("AddImage", hHomeImage); } ViewData["PhotoUrl"] = hHomeImage.ImgUrl; if (filesize != null) hHomeImage.ImgSize = filesize / 1024; else hHomeImage.ImgSize = 0; hHomeImage.InputTime = DateTime.Now; hHomeImageRepository.Save(hHomeImage); if (photo!=null) { foreach (var item in photo) { if (item != null) { var extention = Path.GetExtension(item.FileName); if (extention == ".aspx" || extention == ".html" || extention == ".exe" || extention == ".asp" || extention == ".jsp" || extention == ".js" || extention == ".htm" || extention == ".php") { return Content("<script>alert('不能上傳這類型文件')</script>"); } NewFile newFile = new NewFile(); string fileName = DateTime.Now.ToString("yyyyMMddhhmm") + "_img_" + Path.GetFileName(item.FileName); newFile.NewId = hHomeImage.ID; newFile.Name = fileName; newFile.FileSize = item.ContentLength; newFile.isImg = true; item.SaveAs(Server.MapPath("~/UpLoadFiles/" + fileName));//保存到物理路徑 newFileBLL.Save(newFile);//保存新聞附件 } } } hHomeImage.HtmlUrl = "/ljzcHtml/" + DateTime.Now.ToString("yyyyMMddHHmm") + "hmIndex" + hHomeImage.ID + ".htm";//靜態頁地址 hHomeImageRepository.Update(hHomeImage);//修改圖片表 this.isHtmlPage(hHomeImage);//分頁 XElement xe = XElement.Load(Server.MapPath(path)); XElement element = new XElement(XName.Get("img")); element.SetElementValue("id", DateTime.Now.ToString("yyyyMMddhhmmssfff")); element.SetElementValue("title", hHomeImage.Name); element.SetElementValue("path", filepath); xe.Add(element); xe.Save(Server.MapPath(path)); return Content("<script>window.parent.afterImage();</script>"); }
6、前台View中,進行uploadify的配置,以及Ckediter的使用。
7、同樣這里涉及到文件的上傳,所以Form的格式為“multipart/form-data”。
8、添加uploadify的JS和Css。其中還有一個uploadify.swf,上傳文件時滾動條的動畫效果。
<script src="@Url.Content("~/Scripts/jquery.uploadify.js")" type="text/javascript"></script> <link href="@Url.Content("~/Content/uploadify.css")" rel="stylesheet" />
9、其中uploadify中有個方法是:onUploadSuccess,上傳成功之后執行的方法,為了達到無刷新上傳圖片,使用
$("#PersonImage").attr("src", data).show(),進行顯示圖片。data為圖片的路徑地址。
10、上傳圖片上傳到了哪里??uploadify有一個uploader屬性:指定上傳后指定的地方:(@Url.Content("~/Common/Upload"))。返回值為路徑的字符串。
[HttpPost] public ActionResult Upload(HttpPostedFileBase FileData, string folder) { string result = ""; folder = "/Homeimages"; if (FileData != null) { try { string filename = Path.GetFileName(FileData.FileName);//獲得文件名 string extname = Path.GetExtension(FileData.FileName);//獲得文件擴展名 string saveName = Guid.NewGuid().ToString("N") + extname;//實際保存文件名 saveFile(FileData, folder, saveName);//保存文件 result = folder + "/" + saveName; } catch { result = ""; } } return Content(result); } [NonAction] private void saveFile(HttpPostedFileBase postedFile, string filepath, string saveName) { string phyPath = Request.MapPath(filepath + "/"); if (!Directory.Exists(phyPath)) { Directory.CreateDirectory(phyPath); } try { postedFile.SaveAs(phyPath + saveName); } catch (Exception e) { throw new ApplicationException(e.Message); } }
11、簡單介紹uploadify其他屬性: (官網介紹)
folder : 上傳文件存放的目錄 。
queueID : 文件隊列的ID,該ID與存放文件隊列的div的ID一致。
queueSizeLimit : 當允許多文件生成時,設置選擇文件的個數,默認值:999 。
multi : 設置為true時可以上傳多個文件。
auto : 設置為true當選擇文件后就直接上傳了,為false需要點擊上傳按鈕才上傳 。
fileDesc : 這個屬性值必須設置fileExt屬性后才有效,用來設置選擇文件對話框中的提示文本。
fileExt : 設置可以選擇的文件的類型,格式如:'*.doc;*.pdf;*.rar' 。
sizeLimit : 上傳文件的大小限制 。
simUploadLimit : 允許同時上傳的個數 默認值:1 。
buttonText : 瀏覽按鈕的文本,默認值:BROWSE 。
buttonImg : 瀏覽按鈕的圖片的路徑 。
hideButton : 設置為true則隱藏瀏覽按鈕的圖片 。
rollover : 值為true和false,設置為true時當鼠標移到瀏覽按鈕上時有反轉效果。
width : 設置瀏覽按鈕的寬度 ,默認值:110。
height : 設置瀏覽按鈕的高度 ,默認值:30。
12、前台View代碼如下:
@using (Html.BeginForm("AddImage", "Home", FormMethod.Post, new { enctype = "multipart/form-data" })) { <script src="@Url.Content("~/Scripts/jquery.uploadify.js")" type="text/javascript"></script> <link href="@Url.Content("~/Content/uploadify.css")" rel="stylesheet" /> <script type="text/javascript"> $(function () { $("#custom_file_upload").uploadify({ auto: true, buttonClass: "selectbtnClass", swf: '@Url.Content("~/Content/uploadify.swf")', buttonCursor: "arrow", buttonText: "請選擇圖片..", //debug: true, fileObjName: "fileData", fileSizeLimit: "20000kB", fileTypeDesc: "圖片文件", fileTypeExts: "*.jpg;*.gif;*.png", queueID: "custom-queue", method: "post", uploader: '@Url.Content("~/Common/Upload")', //preventCaching: true, progressData: "percentage", queueSizeLimit: 10, removeComplete: true, removeTimeout: 1, requeueErrors: true, successTimeOut: 5, uploadLimit: 10, width: 100, height: 30, onUploadSuccess: function (file, data, response) { if (file != null) { $("#PersonImage").attr("src", data).show(); var hideDiv = $("<div>").attr("id", "ImgID"); var filename = $("<input>").attr("name", "filename").attr("type", "hidden").attr("value", file.name); var extname = $("<input>").attr("name", "extname").attr("type", "hidden").attr("value", file.type); var filesize = $("<input>").attr("name", "filesize").attr("type", "hidden").attr("value", file.size); var filepath = $("<input>").attr("name", "filepath").attr("type", "hidden").attr("value", data); hideDiv.append(filename); hideDiv.append(extname); hideDiv.append(filesize); hideDiv.append(filepath); $("#custom-queue").append(hideDiv); } else { alert("上傳錯誤!"); } }, onCancel: function (file) { alert(file.name); } }); }); </script> <table id="ListImage"> <tr> <td> 圖片標題</td> <td>@Html.TextBoxFor(p => p.Name)</td> </tr> <tr><td>圖片內容</td> <td>@Html.TextAreaFor(p => p.Content, new { @class = "ckeditor", style = "width:60px;" })</td> </tr> <tr> <td>添加附件</td> <td> <table style="width: 552px; height: 30px" id="idMultiTable"></table> <br /> <input id="btnAddRow" onclick="addTableRow(-1);" value="添加一組" type="button"/> </td> </tr> <tr> <td> <div> <p style="margin-top:5px;font-size:14px;font-weight:bold;"></p> <p style="margin-top:5px;font-size:14px;font-weight:bold;"><span id="result"></span></p> <div id="custom-queue"></div> <p>選擇圖片:</p><br /> </div> </td> <td><input id="custom_file_upload" type="file" name="Filedata" /></td> </tr> <tr> <td> 顯示圖片: </td> <td> <input type="image" id="PersonImage" name ="PersonImage" style="width:240px; display:none;" src="@ViewData["PhotoUrl"]" /> </td> </tr> <tr> <td colspan="2"><center><input type="submit" id="btnSave" name="button" class="button" value="保存" /></center></td> </tr> </table> }
三、至此“添加圖片新聞”已經完成,接下來實現帶分頁的靜態頁(StreamWriter)。
-
- 添加完新聞之后,調用isHtmlPage(News news)方法,參數為整個實體(添加完后的實體里面有新聞的路徑、內容)
- 根據傳入的內容判斷是否為分頁。Ckediter的分頁按鈕如下:


- http://localhost:16494/CurrentPage1a201308101545nwIndex2142.htm
- http://localhost:16494/CurrentPage2a201308101545nwIndex2142.htm
- 他會自動兩個鏈接,CurrentPage {n} 來區分。
- 使用正則表達式來匹配是否有分頁符按鈕。
- 使用StreamReader進行讀取.html的模版,使用Replace進行替換內容。
- 使用StreamWriter以流的方式進行輸出。
#region 公共生成靜態頁 /// <summary> /// 判斷是否分頁 /// </summary> /// <param name="hHomeImage"></param> private void isHtmlPage(New nNew) { string pattern = @"<div\s+style="page-break-after:\s+always[;]?">\s+<span\s+style="display:\s+none[;]?">&nbsp;</span></div>";//[;]?在chrome和ff中插入的代碼中是比較嚴謹的都是style=“page-break-after:always;”(注意這個分號,ie中是沒有的) string[] contentarr = System.Text.RegularExpressions.Regex.Split(HttpUtility.HtmlEncode(nNew.Content), pattern);//為了html頁面分頁 if (contentarr.Length <= 1) { this.publicHtmlHomeImage(nNew, nNew.HtmlUrl, 1); } else { for (int i = 0; i <= contentarr.Length; i++) { string htmlUrl = nNew.HtmlUrl.Substring(0, 10) + "CurrentPage" + i + "a" + nNew.HtmlUrl.Substring(10); if (i == 0) htmlUrl = nNew.HtmlUrl; this.publicHtmlHomeImage(nNew, htmlUrl, i); } } } /// <summary> /// 公共生成靜態頁 /// </summary> /// <param name="hHomeImage">實體類</param> /// <param name="pathUrl">靜態頁面路徑</param> /// <param name="index">頁碼</param> private void publicHtmlHomeImage(New nNew, string pathUrl, int index) { System.Text.Encoding code = System.Text.Encoding.GetEncoding("GB2312"); // 讀取模板文件 string temp = System.Web.HttpContext.Current.Server.MapPath("~/qiantaiContent.htm"); string str = ""; using (StreamReader sr = new StreamReader(temp, code)) { str = sr.ReadToEnd(); // 讀取文件 } List<string> list = htmlPageData.htmlPageList(nNew.Content, nNew.HtmlUrl, index); // 替換內容 這時,模板文件已經讀入到名稱為str的變量中了 str = str.Replace("$document", Enum.GetName(typeof(TianxinWeb.Webs.Models.Document), nNew.Document)); str = str.Replace("$Title", nNew.Title); //模板頁中的標簽 str = str.Replace("$Wenhao", nNew.Wenhao); str = str.Replace("$CreatDate", nNew.CreatDate.Value.ToString()); str = str.Replace("$htmlPage", list[0]);//分頁 str = str.Replace("$Content", list[1]);//內容 var iNf = _NewFileBLL.IEnumrable_NewFile(nNew.ID, false); string fujian = ""; foreach (var item in iNf) { fujian += "<div style='height:22px; line-height:22px;'><a color=red href=../UpLoadFiles/" + item.Name + ">" + item.Name + "</a></div>"; } str = str.Replace("$htmlfujian", fujian);//附件 // 寫文件 pathUrl = System.Web.HttpContext.Current.Server.MapPath(pathUrl); using (StreamWriter sw = new StreamWriter(pathUrl, false, code)) { sw.Write(str); sw.Flush(); } } #endregion
/// <summary> /// html分頁 前台頁面分頁和樣式 /// </summary> /// <param name="Content">內容</param> /// <param name="htmlUrl"></param> /// <param name="currentPageIndex"></param> /// <returns></returns> public static List<string> htmlPageList(string Content, string htmlUrl, int?currentPageIndex) { if (currentPageIndex == null || currentPageIndex==0) currentPageIndex = 1; List<string> strList = new List<string>();//存頁碼和內容 string pattern = @"<div\s+style="page-break-after:\s+always[;]?">\s+<span\s+style="display:\s+none[;]?">&nbsp;</span></div>";//[;]?在chrome和ff中插入的代碼中是比較嚴謹的都是style=“page-break-after:always;”(注意這個分號,ie中是沒有的) string[] contentarr = System.Text.RegularExpressions.Regex.Split(HttpUtility.HtmlEncode(Content), pattern); int pageCount = contentarr.Length; //總頁數 int CurrentPage = currentPageIndex.Value;//當前頁 string outputContent = "";//要輸出的內容 string pageStr = "";//分頁字符串 if (pageCount <= 1)//只有一頁 不分頁 outputContent = Content; else { pageStr += "共 <span class='count'>" + pageCount + "</span> 頁 "; if (CurrentPage != 1) pageStr += "<a class='prevA' href =" + htmlUrl.Substring(0, 10) + "CurrentPage" + (CurrentPage - 1) + "a" + htmlUrl.Substring(10) + ">上一頁</a>"; for (int i = 1; i <= pageCount; i++) { if (i == CurrentPage) pageStr += ("<span class='activeA'>" + i + "</span>"); else pageStr += ("<a class='numA' href =" + htmlUrl.Substring(0, 10) + "CurrentPage" + i + "a" + htmlUrl.Substring(10) + ">" + i + "</a>"); } if (CurrentPage != pageCount) { pageStr += "<a class='nextA' href =" + htmlUrl.Substring(0, 10) + "CurrentPage" + (CurrentPage + 1) + "a" + htmlUrl.Substring(10) + ">下一頁</a>"; } outputContent = contentarr[CurrentPage - 1].ToString().Replace(" ", " "); outputContent = HttpUtility.HtmlDecode(outputContent); } strList.Add(pageStr);//分頁樣式 strList.Add(outputContent); return strList; }
四、今天情人節,借着這個機會,祝願所有的程序員,情人節快樂,終成眷屬。今天寫的內容也挺多的,寫博客確實費時和費神,希望朋友們也多多支持下,如果對您有一點點幫助的話,右下角“推薦”一下。
