首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASP.NET 產生靜態 HTML 頁面並支援分頁的完整實作

     編輯:ASP.NET 基礎

架構概覽

採用「模板檔 + 資料庫 + 靜態化產生器」架構:

  1. template.html:靜態頁面模板,預留 {Title}、{Content}、{Pager} 等置換標記。
  2. NewsAdd.aspx:後台編輯頁,輸入標題與內容(支援 FCKeditor)。
  3. NewsAdd.aspx.cs:核心邏輯——存資料庫、切割長內容分頁、讀取模板、置換標記、寫入 .shtml 靜態檔。

1. 靜態頁面模板 template.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
    <title>{Title}</title>
</head>
<body>
    <div align="center"><h1>{Title}</h1></div>
    <div>瀏覽 <font color="red"><script src="/ClickCount.aspx?NewsId={NewsId}"></script></font> 次  時間:{Time}</div>
    <div>{Content}</div>
    <div>{Pager}</div>
    <!-- 評論表單區塊 -->
    <form action="/AddComment.aspx" method="post">
        <input type="hidden" name="NewsId" value="{NewsId}" />
        <textarea name="CommentContent"></textarea>
        <input type="submit" value="發表評論" />
    </form>
</body>
</html>

置換標記:{Title}、{NewsId}、{Time}、{Content}、{Pager}。

2. 後台編輯頁 NewsAdd.aspx (重點)

<%@ Page Language="C#" ValidateRequest="false" CodeFile="NewsAdd.aspx.cs" Inherits="NewsAdd" %>
<%@ Register TagPrefix="FCK" Namespace="FredCK.FCKeditorV2" Assembly="FredCK.FCKeditorV2" %>
<html><body>
<form id="form1" runat="server">
    標題:<asp:TextBox ID="txtTitle" runat="server" Width="400px" /><br />
    內容:<FCK:FCKeditor ID="txtContent" runat="server" Height="400px" Width="70%" BasePath="~/FCKeditor/" /><br />
    <asp:Button ID="btnPublish" runat="server" Text="發布靜態頁" OnClick="btnPublish_Click" />
    <asp:Label ID="lblMsg" runat="server" ForeColor="Green" />
</form>
</body></html>

3. 核心產生邏輯 NewsAdd.aspx.cs

using System;
using System.Data;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI;

public partial class NewsAdd : Page
{
    protected void btnPublish_Click(object sender, EventArgs e)
    {
        string title = txtTitle.Text.Trim();
        string rawContent = txtContent.Value.Trim(); // FCKeditor 內容
        if (string.IsNullOrEmpty(title) || string.IsNullOrEmpty(rawContent))
        {
            lblMsg.Text = "標題與內容不可為空";
            return;
        }

        // 1. 存入資料庫取得 NewsId
        string fileNameBase = DateTime.Now.ToString("yyMMddHHmmss");
        string fileName = fileNameBase + ".shtml";
        string connStr = System.Configuration.ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
        int newsId = 0;
        using (SqlConnection conn = new SqlConnection(connStr))
        {
            string sql = "INSERT INTO News (Title, Content, FileName) VALUES (@Title, @Content, @FileName); SELECT SCOPE_IDENTITY()";
            using (SqlCommand cmd = new SqlCommand(sql, conn))
            {
                cmd.Parameters.AddWithValue("@Title", title);
                cmd.Parameters.AddWithValue("@Content", rawContent);
                cmd.Parameters.AddWithValue("@FileName", fileName);
                conn.Open();
                newsId = Convert.ToInt32(cmd.ExecuteScalar());
            }
        }

        // 2. 依字數切割分頁 (每頁約 2000 字)
        int pageSize = 2000;
        string[] pages = SplitContentByLength(rawContent, pageSize);
        int totalPages = pages.Length;

        // 3. 讀取模板
        string templatePath = Server.MapPath("~/Templates/template.html");
        string template = File.ReadAllText(templatePath, Encoding.GetEncoding("gb2312"));

        // 4. 逐頁產生靜態檔
        string outputDir = Server.MapPath($"~/NewsFiles/{DateTime.Now:yyMMdd}/");
        if (!Directory.Exists(outputDir)) Directory.CreateDirectory(outputDir);

        for (int i = 0; i < totalPages; i++)
        {
            string pageFile = (i == 0) ? fileNameBase + ".shtml" : $"{fileNameBase}_{i}.shtml";
            string pagePath = Path.Combine(outputDir, pageFile);

            string html = template
                .Replace("{Title}", title)
                .Replace("{NewsId}", newsId.ToString())
                .Replace("{Time}", DateTime.Now.ToString("yyyy/MM/dd"))
                .Replace("{Content}", pages[i])
                .Replace("{Pager}", BuildPagerHtml(fileNameBase, i, totalPages));

            File.WriteAllText(pagePath, html, Encoding.GetEncoding("gb2312"));
        }

        lblMsg.Text = $"發布成功!共產生 {totalPages} 頁靜態檔案。";
    }

    /// 依指定長度切割內容,盡量在標點符號處斷行
    private string[] SplitContentByLength(string content, int maxLen)
    {
        List result = new List();
        while (content.Length > maxLen)
        {
            int cut = content.LastIndexOfAny(new[] { '。', '?', '!', '\n' }, maxLen);
            if (cut <= 0) cut = maxLen;
            result.Add(content.Substring(0, cut + 1));
            content = content.Substring(cut + 1);
        }
        if (content.Length > 0) result.Add(content);
        return result.ToArray();
    }

    /// 產生分頁導覽 HTML
    private string BuildPagerHtml(string baseName, int currentIndex, int totalPages)
    {
        if (totalPages <= 1) return string.Empty;

        StringBuilder sb = new StringBuilder();
        sb.Append("
"); // 上一頁 if (currentIndex > 0) { string prevFile = (currentIndex == 1) ? baseName + ".shtml" : $"{baseName}_{currentIndex - 1}.shtml"; sb.Append($"上一頁 "); } // 頁碼 for (int p = 1; p <= totalPages; p++) { string pageFile = (p == 1) ? baseName + ".shtml" : $"{baseName}_{p - 1}.shtml"; if (p == currentIndex + 1) sb.Append($"{p} "); else sb.Append($"{p} "); } // 下一頁 if (currentIndex < totalPages - 1) { string nextFile = $"{baseName}_{currentIndex + 1}.shtml"; sb.Append($"下一頁"); } sb.Append("
"); return sb.ToString(); } }

關鍵技術點解析

  • ValidateRequest="false":允許 FCKeditor 提交 HTML 內容,需自行做 XSS 過濾。
  • 參數化查詢:防止 SQL Injection,取得自增 NewsId 供點擊統計、評論關聯。
  • 智慧分頁切割:SplitContentByLength 優先在句號、換行處斷行,避免截斷句子。
  • 日期目錄分層:NewsFiles/yyMMdd/ 避免單一目錄檔案過多影響檔案系統效能。
  • 編碼一致性:模板讀取、檔案寫入均指定 gb2312,符合中文舊系統相容需求;新專案建議全面改用 UTF-8。

擴充建議

  1. 加入 圖片路徑自動轉換:將編輯器內相對路徑轉為絕對 CDN 路徑。
  2. 支援 多模板切換:依新聞分類套用不同版型。
  3. 整合 CDN 刷新 API:發布後自動推送靜態檔至 CDN 節點。
  4. 建立 靜態檔索引表:記錄每篇新聞對應的靜態檔路徑,便於管理與重新產生。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved