ASP 实例

四个可直接改造的小例子:留言板、登录、文件列表、分页列表。

Advanced
Key Points把前面所有知识点串成能跑的小功能:读表单、查库、分页、写文件、控制权限。

1. 留言板:写入与展示

ASP
<%@ Language="VBScript" CodePage="65001" %>
<% Option Explicit %>
<% Response.Buffer = True %>
<!-- #include virtual="/includes/conn.asp" -->
<%
    Response.Charset = "UTF-8"
    Response.ContentType = "text/html"

    ' 处理提交
    If Request.ServerVariables("REQUEST_METHOD") = "POST" Then
        Dim name, body, cmd
        name = Trim(Request.Form("name"))
        body = Trim(Request.Form("body"))

        If name <> "" And body <> "" Then
            Set cmd = Server.CreateObject("ADODB.Command")
            Set cmd.ActiveConnection = conn
            cmd.CommandText = "INSERT INTO messages (name, body, created) VALUES (?, ?, GETDATE())"
            cmd.Parameters.Append cmd.CreateParameter("n", 200, 1, 50, name)
            cmd.Parameters.Append cmd.CreateParameter("b", 203, 1, 4000, body)
            cmd.Execute
        End If

        Response.Redirect "board.asp"        ' PRG:防刷新重复提交
    End If

    ' 读取列表
    Dim rs
    Set rs = conn.Execute("SELECT TOP 20 name, body, created FROM messages ORDER BY id DESC")
%>
<!DOCTYPE html>
<html><body>
<h1>留言板</h1>

<form method="post">
  昵称:<input name="name" maxlength="50"><br>
  内容:<textarea name="body" rows="4" cols="40"></textarea><br>
  <button type="submit">提交</button>
</form>

<hr>
<% Do While Not rs.EOF %>
  <div>
    <strong><%= Server.HTMLEncode(rs("name")) %></strong>
    <small><%= rs("created") %></small>
    <p><%= Server.HTMLEncode(rs("body")) %></p>
  </div>
<%   rs.MoveNext
   Loop %>
</body></html>
Output
留言板

昵称: Ada
内容: 第一条留言

Ada  2026/11/3 14:20:01
第一条留言

Redirect after a successful POST (PRG) so F5 does not insert again. Rendering a success page directly means every refresh adds a message.

2. 登录与权限

ASP
<%-- login.asp --%>
<%
    If Request.ServerVariables("REQUEST_METHOD") = "POST" Then
        Dim cmd, rs, pwd
        Set cmd = Server.CreateObject("ADODB.Command")
        Set cmd.ActiveConnection = conn
        cmd.CommandText = "SELECT id, name, pwd_hash FROM users WHERE name = ?"
        cmd.Parameters.Append cmd.CreateParameter("n", 200, 1, 50, Trim(Request.Form("name")))
        Set rs = cmd.Execute

        If Not rs.EOF Then
            ' 实际项目必须用哈希比对,不能存明文
            If HashPassword(Request.Form("pwd")) = rs("pwd_hash") Then
                Session("uid") = rs("id")
                Session("uname") = rs("name")
                Response.Redirect "admin.asp"
            End If
        End If
    End If
%>
<form method="post">
  用户名:<input name="name">
  密码:<input type="password" name="pwd">
  <button type="submit">登录</button>
</form>
ASP
<%-- admin.asp:页面顶部做权限校验 --%>
<%
    If IsEmpty(Session("uid")) Then
        Response.Redirect "login.asp"
    End If
%>
<h1>欢迎,<%= Server.HTMLEncode(Session("uname")) %></h1>

Put the auth check at the very top, before any output. Placed mid-page, unauthenticated users already see content and Redirect fails because headers are gone.

Code after Response.Redirect may still run (with Buffer=True it ends, but do not rely on it). Call Response.End right after so nothing else executes.

3. 文件列表

ASP
<%
    Dim fso, folder, f
    Set fso = Server.CreateObject("Scripting.FileSystemObject")
    Set folder = fso.GetFolder(Server.MapPath("/uploads"))
%>
<table>
  <tr><th>文件名</th><th>大小</th><th>修改时间</th><th>操作</th></tr>
<% For Each f In folder.Files %>
  <tr>
    <td><%= Server.HTMLEncode(f.Name) %></td>
    <td><%= FormatNumber(f.Size / 1024, 1) %> KB</td>
    <td><%= f.DateLastModified %></td>
    <td><a href="download.asp?f=<%= Server.URLEncode(f.Name) %>">下载</a></td>
  </tr>
<% Next %>
</table>
Output
文件名            大小        修改时间            操作
report.pdf       180.0 KB    2026/11/2 17:40:55   下载
notes.txt        1.0 KB      2026/11/3 9:02:11    下载
ASP
<%-- download.asp --%>
<%
    Dim fname, path
    fname = Request.QueryString("f")

    ' 关键:只允许单纯的文件名
    If InStr(fname, "..") > 0 Or InStr(fname, "/") > 0 Or InStr(fname, "\") > 0 Then
        Response.Status = "400 Bad Request"
        Response.End
    End If

    path = Server.MapPath("/uploads/" & fname)
    If Not fso.FileExists(path) Then
        Response.Status = "404 Not Found"
        Response.End
    End If

    Response.ContentType = "application/octet-stream"
    Response.AddHeader "Content-Disposition", "attachment; filename=" & fname

    Dim st
    Set st = Server.CreateObject("ADODB.Stream")
    st.Type = 1
    st.Open
    st.LoadFromFile path
    Response.BinaryWrite st.Read
    st.Close
    Response.End
%>

Without validation, download.asp?f=../../conn.asp downloads the file holding your database password. Restrict names to alphanumerics and dots and reject every path separator.

4. 分页列表

ASP
<%
    Dim page, size, total, pages, offset, rs
    page = CLng("0" & Request.QueryString("page"))
    If page < 1 Then page = 1
    size = 10

    ' 总数
    total = conn.Execute("SELECT COUNT(*) AS c FROM products")("c")
    pages = Int((total + size - 1) / size)
    If page > pages And pages > 0 Then page = pages
    offset = (page - 1) * size

    Set rs = conn.Execute( _
        "SELECT id, name, price FROM products ORDER BY id " & _
        "OFFSET " & offset & " ROWS FETCH NEXT " & size & " ROWS ONLY")
%>
<table>
<% Do While Not rs.EOF %>
  <tr>
    <td><%= rs("id") %></td>
    <td><%= Server.HTMLEncode(rs("name")) %></td>
    <td>¥<%= FormatNumber(rs("price"), 2) %></td>
  </tr>
<%   rs.MoveNext
   Loop %>
</table>

<p>
  第 <%= page %> / <%= pages %> 页,共 <%= total %> 条
  <% If page > 1 Then %>
    <a href="?page=<%= page - 1 %>">上一页</a>
  <% End If %>
  <% If page < pages Then %>
    <a href="?page=<%= page + 1 %>">下一页</a>
  <% End If %>
</p>
Output
第 2 / 5 页,共 48 条
上一页 下一页

CLng("0" & Request.QueryString("page")) is the classic empty guard: an empty parameter becomes "0" and CLng succeeds. Range-check afterwards so page is never negative or past the end.

OFFSET slows down as it grows: page 1000 makes the database skip twenty thousand rows. For large data switch to keyset paging (continue from the last id of the previous page), which is O(1) per page.

把例子改成自己的

ExampleReuse for
留言板评论、工单、反馈
登录任何需要权限的后台
文件列表文档下载中心、素材库
分页列表商品、文章、用户列表

All four share one skeleton: read parameters, validate, query or touch files, escape on output. Changing the business means changing the SQL and fields, not the structure.

Friends & Partners