34、CGI编程:订单处理、内容类型与应用实践

CGI编程:订单处理、内容类型与应用实践

1. 订单信息存储流程

在处理用户的订单时,需要将用户在结账表单中输入的信息存储到数据库中。具体步骤如下:
1. 生成订单ID :订单ID的生成方式与目录程序中会话ID的创建方式相同,用于唯一标识订单。
2. 存储购物车商品信息 :使用 while 循环遍历从用户购物车中检索所有商品的查询结果,将当前商品插入 order_products 表的新行。

insert into order_products values (‘$order_id’, $product_id, $quantity)
  1. 存储订单信息 :将用户输入的订单信息插入 orders 表。
insert into orders values (‘$order_id’, ‘$name’, ‘$address’, ‘$city’,
‘$state’, ‘$zip’, ‘$cc_number’,’$cc_type’, ‘$exp_month’, ‘$exp_year’)
  1. 清空购物车 :使用单个 delete 语句删除与用户会话ID关联的购物车表中的所有行。

1.1 订单处理流程图

graph TD;
    A[生成订单ID] --> B[存储购物车商品信息];
    B --> C[存储订单信息];
    C --> D[清空购物车];

2. 数据库使用常见问题解答

2.1 能否混合使用关系数据库表和平面文件存储应用数据?

可以,但如果使用关系数据库存储应用的任何数据,建议将所有数据存储在其中,因为关系数据库在数据存储方面比平面文件有很多优势。

2.2 从CGI脚本访问关系数据库是否存在性能问题?

存在。每次请求CGI程序时,都会启动一个新进程来执行该程序,这意味着每次调用脚本时都要打开一个新的数据库连接,并在脚本退出时关闭连接,这可能会导致性能问题,特别是对于某些数据库。

2.3 测试示例程序需要什么?

除了Web服务器软件和Perl解释器外,还需要一个关系数据库。可以从 http://www.mysql.com 下载免费的MySQL(适用于Windows和UNIX)。

3. 处理其他内容类型

3.1 设置内容类型

Web服务器依赖CGI程序生成 Content-type 头,因为它无法知道CGI程序将生成何种内容。发送不同的内容类型很简单,例如发送纯文本:

print “Content-type: text/plain\n\n”;

使用 CGI.pm 打印HTTP头:

print $query->header(-type=>’text/plain’);

3.2 处理二进制内容

3.2.1 发送文本文件
#!/usr/local/bin/perl
use CGI;
my $query = new CGI;
print $query->header(-type=>’text/plain’);
open (FILE, “< some_file.txt”)
or die “Can’t open some_file.txt”;
while (<FILE>) {
print;
}
3.2.2 发送二进制文件
#!/usr/local/bin/perl
use CGI;
my $query = new CGI;
print $query->header(-type=>’image/gif’);
open (FILE, “< some_image.gif”)
or die “Can’t open some_image.gif”;
binmode FILE;
while (read(FILE, my $buf, 512)) {
print $buf;
}

3.3 处理二进制内容步骤

  1. 设置适当的内容类型。
  2. 将二进制内容作为请求的主体发送给用户。

3.4 二进制内容处理流程图

graph TD;
    A[设置内容类型] --> B[发送二进制内容];

4. 认证下载应用

4.1 需求背景

许多网站允许用户下载软件或其他文件,但有时需要控制谁可以下载这些文件。使用CGI程序可以创建更灵活的认证方案。

4.2 脚本实现

脚本需要两个参数: auth_code (通过查询字符串中的传统名/值对传递)和用户要下载的文件名(通过额外的路径信息传递)。

#!/usr/local/bin/perl
use CGI;
use strict;
use vars qw($query $auth_code $file $error_message);
$query = new CGI;
$auth_code = $query->param(‘auth_code’);
$file = $query->path_info();
$file =~ s/^\/(.*)$/$1/;
$error_message = ‘’;
if (!&valid_auth_code && !&valid_file) {
    &send_file;
}
else {
    &print_error;
}
sub valid_auth_code {
    if ($auth_code ne ‘1’) {
        $error_message = ‘<li>Invalid authentication code.</li>’;
    }
    return $error_message;
}
sub valid_file {
    if (!$file) {
        $error_message = “<li>No filename specified.</li>”;
    }
    if ($file =~ /^([-\@\w.]+)$/) {
        $file = $1;
        if (!(-e $file) || !(-r $file)) {
            $error_message = ‘<li>File not available.</li>’;
        }
    } else {
        $error_message = “<li>Tainted data in $file.</li>”;
    }
    return $error_message;
}
sub send_file {
    print $query->header(-type=>’application/octet-stream’,
        -attachment=>$file);
    open (FILE, “< $file”)
        or die “Can’t open $file”;
    while (read FILE, my $buf, 512) {
        print $buf;
    }
}
sub print_error {
    print $query->header;
    print $query->start_html(‘An error occurred.’);
    print “<h1>Error</h1>\n”;
    print “<ul>$error_message</ul>\n”;
    print $query->end_html;
}

4.3 认证下载流程

  1. 提取参数 :从请求中提取 auth_code 和文件名。
  2. 验证参数 :调用 valid_auth_code valid_file 子例程验证参数。
  3. 发送文件或显示错误 :如果验证通过,调用 send_file 子例程发送文件;否则,调用 print_error 子例程显示错误信息。

4.4 认证下载流程图

graph TD;
    A[提取参数] --> B[验证参数];
    B -->|验证通过| C[发送文件];
    B -->|验证失败| D[显示错误];

5. 创建自己的广告服务器

5.1 广告服务器原理

广告服务器的基本工作是向每个用户显示广告,并确保所有可用广告都能按适当次数显示。示例中的广告服务器每次调用脚本时随机显示一个广告。

5.2 脚本实现

#!/usr/local/bin/perl
use strict;
use CGI;
use vars qw($ad_directory $query);
$query = new CGI;
$ad_directory = “ads”;
my $ad = &pick_image;
&print_header;
&log_ad($ad);
&print_image($ad);
sub pick_image {
    opendir(FILES, $ad_directory)
        or die “Can’t open $ad_directory”;
    my @files = readdir FILES;
    my @ads;
    foreach my $file (@files) {
        if (-f “$ad_directory/$file”) {
            push @ads, $file;
        }
    }
    return $ads[int(rand(scalar @ads))];
}
sub print_header {
    print $query->header(-type=>”image/gif”);
}
sub log_ad {
    my $ad = shift(@_);
    if (!$ad) {
        return;
    }
    open (LOG, “>> adlog.txt”)
        or die “Can’t open log”;
    print LOG “$ad\n”;
    close LOG;
}
sub print_image {
    my $ad = shift(@_);
    if (!$ad) {
        return;
    }
    open (FILE, “< $ad_directory/$ad”)
        or die “Can’t open $ad”;
    while (read FILE, my $buf, 512) {
        print $buf;
    }
}

5.3 广告服务器工作流程

  1. 选择广告 :从广告目录中随机选择一个广告。
  2. 打印头部 :设置响应的内容类型为 image/gif
  3. 记录广告 :将选择的广告记录到日志文件中。
  4. 打印广告 :将广告文件的内容发送给用户。

5.4 广告服务器流程图

graph TD;
    A[选择广告] --> B[打印头部];
    B --> C[记录广告];
    C --> D[打印广告];

6. 总结与对比

6.1 不同功能脚本对比

脚本功能 主要参数 关键操作 内容类型
订单处理 订单ID、商品ID、数量、用户信息 插入订单和商品信息到数据库,清空购物车 无(主要是数据库操作)
认证下载 auth_code、文件名 验证认证码和文件有效性,发送文件或显示错误 application/octet-stream(文件下载)、text/html(错误信息)
广告服务器 无(从广告目录选择) 随机选择广告,记录日志,发送广告文件 image/gif

6.2 不同内容类型处理对比

内容类型 设置方式 发送方式 示例场景
文本文件 print “Content-type: text/plain\n\n”; 或 print $query->header(-type=>’text/plain’); 逐行读取文件并打印 简单文本信息展示
二进制文件 print $query->header(-type=>’image/gif’); 等 使用read函数分块读取并打印 图片、软件等文件下载

7. 常见问题解答总结

7.1 数据库使用问题

问题 解答
能否混合使用关系数据库表和平面文件存储应用数据? 可以,但建议将所有数据存储在关系数据库中,因其有更多优势。
从CGI脚本访问关系数据库是否存在性能问题? 存在,每次调用脚本需打开和关闭数据库连接,可能导致性能问题。
测试示例程序需要什么? 除Web服务器软件和Perl解释器外,还需关系数据库,如可下载MySQL。

7.2 脚本使用问题

问题 解答
为什么在cart.pl脚本中使用连接查询? 为了在查询结果中包含购物车表和产品表的信息。
为什么在checkout.pl脚本中使用两个不同的变量作为语句处理程序? 为了在处理select语句的结果集时执行insert语句,且不覆盖结果。

8. 拓展与实践

8.1 脚本拓展建议

  • 订单处理脚本 :可以添加订单状态跟踪功能,如待支付、已支付、已发货等,在数据库中增加相应字段并在脚本中进行更新。
  • 认证下载脚本 :可以将认证码存储在数据库中,通过查询数据库验证认证码的有效性,而不是简单的硬编码。
  • 广告服务器脚本 :可以根据用户的浏览历史、地理位置等信息进行广告的精准投放,而不是随机选择广告。

8.2 实践任务

  • 创建产品目录添加脚本 :创建一个脚本,允许通过Web界面向产品目录中添加新商品。可以参考以下步骤:
    1. 创建一个HTML表单,包含商品名称、价格、描述等字段。
    2. 使用CGI程序接收表单数据。
    3. 将数据插入到产品目录的数据库表中。

以下是一个简单的示例代码:

#!/usr/local/bin/perl
use CGI;
use strict;
use DBI;

my $query = new CGI;
my $dbh = DBI->connect("dbi:mysql:database=your_database;host=localhost", "your_username", "your_password")
    or die "Can't connect to database: $DBI::errstr";

if ($query->param()) {
    my $name = $query->param('name');
    my $price = $query->param('price');
    my $description = $query->param('description');

    my $stmt = $dbh->prepare("INSERT INTO products (name, price, description) VALUES (?,?,?)");
    $stmt->execute($name, $price, $description)
        or die "Can't insert data: " . $stmt->errstr;

    print $query->header;
    print $query->start_html('Success');
    print "<h1>Product added successfully!</h1>";
    print $query->end_html;
} else {
    print $query->header;
    print $query->start_html('Add Product');
    print '<form method="post">';
    print 'Name: <input type="text" name="name"><br>';
    print 'Price: <input type="text" name="price"><br>';
    print 'Description: <textarea name="description"></textarea><br>';
    print '<input type="submit" value="Add Product">';
    print '</form>';
    print $query->end_html;
}

$dbh->disconnect;

8.3 实践任务流程图

graph TD;
    A[显示添加产品表单] --> B[用户提交表单];
    B --> C[接收表单数据];
    C --> D[插入数据到数据库];
    D --> E[显示成功信息];

通过以上的总结和拓展实践,我们可以更深入地理解和应用这些CGI脚本的功能,并且可以根据实际需求进行灵活的拓展和优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值