嵌入式web服务器BOA+CGI+HTML+MySQL项目实战——Linux

30 篇文章 1 订阅

前言

本文开始是默认环境准备是没有问题的,如果环境没有搭建好,可以参考下面的文章完成环境搭建。
ps:由于本文当时是在刚接触Boa不久就编写的,所以比较混乱,如果希望有个清晰点的demo工程进行参考,可以参考我的新文章:Linux下 基于Boa的应用资源管理系统 SMS

准备环境

操作系统: Ubuntu12.04 LTS (当然在CentOS7下也适用,只不过有些操作需要微调)
环境搭建: 需要 BOA,Apache,CCGI,MySQL,GCC
Linux下嵌入式Web服务器BOA和CGI编程开发
数据库的相关知识——学习笔记 的三
mysql中文乱码问题解决 / C程序插入仍是乱码解决 / 卸载重装教学
扩展: 我还用了bootstrap框架,CSS/JS

工程下载

GitHub:传送门
码云:传送门
在这里插入图片描述

使用方法

环境准备好后,我们在 /var/www 下写HTML文件
在这里插入图片描述
/var/www/cgi-bin 下写c文件(根据boa.conf的配置),编译后命名为.cgi
编译命令仅供参考(pthread dl mysqlclient没用到可以不加)
gcc -o login.cgi login.c cgic.c -lpthread -ldl -lmysqlclient
在这里插入图片描述
程序都写好后,我们开始测试。

1、开启MySQL服务 默认开启在这里插入图片描述
我的程序需要事先 新建用户test,数据库register,表user

mysql -utest -ptest
// 创建新用户test
mysql> create user 'test'@'localhost' identified by 'test';
// 给test用户所有权限
mysql> grant all privileges on *.*  to test@localhost identified by 'test';
// 刷新权限
mysql> flush privileges;
// 创建register数据库
mysql> create database register;
mysql> use register;
// 创建user表
mysql> CREATE TABLE user(username varchar(20) PRIMARY KEY,password varchar(20));

2、开启BOA服务,在/boa-0.94.13/src目录下
执行命令 sudo ./boa (如果你的root权限就直接 ./boa
在这里插入图片描述
3、打开浏览器,访问localhost:端口号 访问的即 /var/www 目录
我直接访问 http://localhost:886/login.html 我的登录页面

在这里插入图片描述
其他页面都是同理。

思路讲解

在这里插入图片描述
开启boa服务器后,我们访问到我们在 /var/www 下编写的HTML文件,显示我们的登录页面。
我们点击“注册”按钮,跳转到 register.html

在这里插入图片描述
点击“注册”按钮,提交form表单信息给cgi-bin/register.cgi
在这里插入图片描述
cgi程序通过 cgiFormString函数试图检索发送给指定字段的字符串。存入变量中。我们连接MySQL数据库
在这里插入图片描述
在这里插入图片描述
将数据写入register数据库中的user表中(此数据库和表需要先建好)
在这里插入图片描述
处理完毕后,跳回 login.html 登录页面
在这里插入图片描述
在这里插入图片描述
现在我们输入数据,点击“登录”,同理将表单发给 login.cgi ,对数据在MySQL数据库中查询后,成功就来到base_config.html 配置页面。
在这里插入图片描述
然后我们输入相应数据,点击“提交”,交给base_config.cgi处理,之后任意发挥就好了。
在这里插入图片描述
我是打印出来,写入系统文件的代码暂时注释了,慎用
在这里插入图片描述
遇到问题可以参考页首的链接


相关源码

login.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>register</title>
<script src="js/jquery-2.2.3.min.js"></script>
<script src="js/jquery-ui.min.js"></script>
<link type="text/css" href="css/jquery-ui.min.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<script src="js/bootstrap.min.js"></script>
<link type="text/css" href="css/login.css" rel="stylesheet">
<script src="js/my.js"></script>
<SCRIPT language = "JavaScript">
    function checkUserName(){    //验证用户名
        var fname = document.myform.username.value;
        var reg=/^[0-9a-zA-Z]/;
        if(fname.length != 0){
            for(i=0;i<fname.length;i++){
                if(!reg.test(fname)){
                    alert("只能输入字母或数字");
                    return false;}
            }
            if(fname.length<4||fname.length>16){
                alert("只能输入4-16个字符")
                return false;
            }
        }
        else{    alert("请输入用户名");
            document.myform.username.focus();
            return false     }
        return true;
    }

    function passCheck(){ //验证密码
        var userpass = document.myform.password.value;
        if(userpass == ""){
            alert("未输入密码 \n" + "请输入密码");
            document.myform.password.focus();
            return false;   }
        if(userpass.length < 6||userpass.length>12){
            alert("密码必须在 6-12 个字符。\n");
            return false;   }
        return true;   }

    function passCheck2(){
        var p1=document.myform.password.value;
        var p2=document.myform.password2.value;
        if(p1!=p2){
            alert("确认密码与密码输入不一致");
            return false;
        }else{
            return true;
        }
    }

    function checkEmail(){
        var Email = document.getElementById("email").value;
        var e = Email.indexOf("@"&&".");
        if(Email.length!=0){
            if(e>0){
                if(Email.charAt(0)=="@"&&"."){
                    alert("符号@和符号.不能再邮件地址第一位");
                return false;
                }
                else{
                    return true;
                }
            }
            else{
                alert("电子邮件格式不正确\n"+"必须包含@符号和.符号!");
                return false;
            }
        }
        else{
            alert("请输入电子邮件!")
            return false;
        }
    }

    function checkbirthday(){    //验证用户名
        var year = document.myform.birthday.value;
        if(year < 1949 || year > 2007){
            alert("年份范围从1949-2007年");
            return false;}
        return true;     }


    function validateform(){
        if(checkUserName()&&passCheck( )&&passCheck2()&&checkEmail()&&checkbirthday())
                return true;
        else
            return false;
    }

    function clearText( ) {
        document.myform.user.value="" ;
        document.myform.password.value="" ;
    }

	//显示隐藏对应的switchPwd()方法:
	$(function(){
        // 通过jqurey修改
        $("#passwordeye").click(function(){
            let type =  $("#password").attr('type')
            if(type === "password"){
                $("#password").attr("type","text");
            }else{
                $("#password").attr("type","password");
            }
        });
	});


</SCRIPT>
</head>
<body>
<img src="img/login_bg.jpg" class="bg">
<div id="head">
	<img src="img/login_head.png" width=100% height=auto />
</div>
<div id="center">
<form name="myform" onSubmit="return validateform( )" enctype="multipart/form-data" action="cgi-bin/login.cgi" method="post" >
	<div class="input-group">
        <h3>用户名:</h3>&nbsp;<input class="form-control" id="username" name="username" type="text"  style="height:40px" value="" placeholder="只能输入字母或数字,4-16个字符"/>
	</div>
	<div class="input-group">        
		<h3>&nbsp;&nbsp;&nbsp;码:</h3>&nbsp;<input class="form-control" id="password" name="password" type="password" style="height:40px"  value="" placeholder="密码长度6-12位"/>
		<span class="input-group-btn">
			<INPUT class="btn btn-default" id="passwordeye" type="button" value="show/hide"">
        </span>
	</div>

	<div id="btn">
		<INPUT class="btn btn-primary" name="loginButton" type="submit" id="Button" value="登录"  onclick="checkUserName()">
		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
		<a href="register.html"><INPUT class="btn btn-primary" name="registerButton" id="Button" type="button" value="注册"></a>
	</div>
</form>
</div>
<div id="bottom">
	<div class="footer" style="color:white;">
     	Copyright &copy; 2013-2019 All Rights Reserved. 备案号:
    </div>
</div>
</body>
</html>

对应 login.c

#include <stdio.h>
#include "cgic.h"
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <mysql/mysql.h>
#include <stdbool.h>

#define SQL_SIZE 256 

int cgiMain(void)
{
    char username[20];
    char password[20];
    char email[40];
	//回显信息到HTML网页cgiHeaderContentType("text/html");
    printf("<html>\n\n");
	printf("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\n");
	printf("<p>\n\n");
    
	if(cgiFormString("username", username, sizeof(username)) != cgiFormSuccess)
    {
        fprintf(stderr, "cgiFormString function username failed");
        //exit(-1);
    }
	printf("用户名:%s\n\n",username);
    printf("<br>\n\n");
	// password gateway server_ip dns subnet_mask dhcp error
	if(cgiFormString("password", password, sizeof(password)) != cgiFormSuccess)
    {
        fprintf(stderr, "cgiFormString function password failed");
        //exit(-1);
    }
	printf("密码:%s\n\n",password);
    printf("<br>\n\n");
/*
	if(cgiFormString("email", email, sizeof(email)) != cgiFormSuccess)
    {
        fprintf(stderr, "cgiFormString function email failed");
        //exit(-1);
    }
	printf("电子邮箱:%s\n\n",phone);
    printf("<br>\n\n");
*/

	/***  将用户信息写入MySQL数据库中  ***/ 
	//数据存储到数据库
	MYSQL* conn;
	bool isAutoCommit;
	
	// 初始化 MySQL
	conn = mysql_init(NULL);
    if(NULL == conn)
    {
        printf("errno:%d error:%s\n",mysql_errno(conn),mysql_error(conn));
        exit(-1);
    }
    
	char ip[16] = "127.0.0.1";
	char user[20] = "test";
	char passwd[20] = "test";
	char database[20] = "register";
	int port = 3306;

	// 尝试与运行在主机上的MySQL数据库引擎建立连接
	if(NULL == mysql_real_connect(conn,ip,user,passwd,database,port,NULL,0))
    {
        printf("---errno:%d error:%s\n\n",mysql_errno(conn),mysql_error(conn));
        exit(-1);
    }
	
	isAutoCommit = true;
	// 根据mysql的autocommit参数设置来决定是否自动提交
	mysql_autocommit(conn,isAutoCommit);

	// 设定数据库编码
	mysql_query(conn,"SET NAMES 'utf8'");
	mysql_query(conn,"SET CHARACTER SET utf8");
	mysql_query(conn,"SET CHARACTER_SET_RESULT = utf8");

    char cmd[SQL_SIZE];
	// 置字节字符串cmd的前SQL_SIZE个字节为零且包括‘\0’
    bzero(cmd, SQL_SIZE);
	// 创建user表
    // strcpy(cmd, "CREATE TABLE user(username varchar(20) PRIMARY KEY,password varchar(20));");

	// 将sql语句写入cmd变量
	sprintf(cmd, "select * from user where username='%s' and password='%s';",username,password);

	MYSQL_RES *res;
	MYSQL_ROW row;
	
	// 向与指定的连接标识符关联的服务器中的当前活动数据库发送一条查询
	if(mysql_query(conn,cmd) != 0)
	{
		printf("errno:%d error:%s\n\n",mysql_errno(conn),mysql_error(conn));
		exit(-1);
	}
	
	int num_fields = mysql_field_count(conn);
	if(num_fields == 0)
	{
		printf("errno:%d error:%s\n",mysql_errno(conn),mysql_error(conn));
		return -1;	
	}
	
	res = mysql_store_result(conn);
	if(NULL == res)
	{
		printf("errno:%d error:%s\n",mysql_errno(conn),mysql_error(conn));
		return -1;
	}
	
	printf("<br>\n\n");
	printf("<br>\n\n");
	int count = 0;
	while((row = mysql_fetch_row(res)))
	{
		char arr[1000];
		int i = 0;
		for( ; i<num_fields; i++)
		{
			printf("%s ",row[i]);
		}
		printf("\n\n");
		printf("<br>\n\n");
		count++;
	}	
	mysql_free_result(res);

	if(count != 0)
	{
		printf("<p>登陆成功</p>\n\n");
		sleep(1);
		printf("<meta http-equiv=Refresh content=1;URL=../base_config.html>\n"); 
	}
	else
	{
		printf("<p>帐号或密码错误</p>\n\n");
		sleep(1);
		printf("<meta http-equiv=Refresh content=1;URL=../login.html>\n"); 
	}

	//printf("<p></p>\n\n");

	return 0;
}

register.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>register</title>
<script src="js/jquery-2.2.3.min.js"></script>
<script src="js/jquery-ui.min.js"></script>
<link type="text/css" href="css/jquery-ui.min.css" rel="stylesheet">
<link type="text/css" href="css/register.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<script src="js/bootstrap.min.js"></script>
<script src="js/my.js"></script>
<SCRIPT language = "JavaScript">
    function checkUserName(){    //验证用户名
        var fname = document.myform.username.value;
        var reg=/^[0-9a-zA-Z]/;
        if(fname.length != 0){
            for(i=0;i<fname.length;i++){
                if(!reg.test(fname)){
                    alert("只能输入字母或数字");
                    return false;}
            }
            if(fname.length<4||fname.length>16){
                alert("只能输入4-16个字符")
                return false;
            }
        }
        else{    alert("请输入用户名");
            document.myform.username.focus();
            return false     }
        return true;
    }

    function passCheck(){ //验证密码
        var userpass = document.myform.password.value;
        if(userpass == ""){
            alert("未输入密码 \n" + "请输入密码");
            document.myform.password.focus();
            return false;   }
        if(userpass.length < 6||userpass.length>12){
            alert("密码必须在 6-12 个字符。\n");
            return false;   }
        return true;   }

    function passCheck2(){
        var p1=document.myform.password.value;
        var p2=document.myform.password2.value;
        if(p1!=p2){
            alert("确认密码与密码输入不一致");
            return false;
        }else{
            return true;
        }
    }

    function checkEmail(){
        var Email = document.getElementById("email").value;
        var e = Email.indexOf("@"&&".");
        if(Email.length!=0){
            if(e>0){
                if(Email.charAt(0)=="@"&&"."){
                    alert("符号@和符号.不能再邮件地址第一位");
                return false;
                }
                else{
                    return true;
                }
            }
            else{
                alert("电子邮件格式不正确\n"+"必须包含@符号和.符号!");
                return false;
            }
        }
        else{
            alert("请输入电子邮件!")
            return false;
        }
    }

    function checkbirthday(){    //验证用户名
        var year = document.myform.birthday.value;
        if(year < 1949 || year > 2007){
            alert("年份范围从1949-2007年");
            return false;}
        return true;     }


    function validateform(){
        if(checkUserName()&&passCheck( )&&passCheck2()&&checkEmail()&&checkbirthday())
                return true;
        else
            return false;
    }

    function clearText( ) {
        document.myform.user.value="" ;
        document.myform.password.value="" ;
    }

	//显示隐藏对应的switchPwd()方法:
	$(function(){
        // 通过jqurey修改
        $("#passwordeye").click(function(){
            let type =  $("#password").attr('type')
            if(type === "password"){
                $("#password").attr("type","text");
            }else{
                $("#password").attr("type","password");
            }
        });
		$("#passwordeye2").click(function(){
            let type =  $("#password2").attr('type')
            if(type === "password"){
                $("#password2").attr("type","text");
            }else{
                $("#password2").attr("type","password");
            }
        });
	});

</SCRIPT>
</head>
<body>
<img src="img/login_bg.jpg" class="bg">
<div id="head">
	<img src="img/register_head.png" width=100% height=auto />
</div>
<div id="center">
<form name="myform" onSubmit="return validateform( )" enctype="multipart/form-data" action="cgi-bin/register.cgi" method="post" >
	<div class="input-group">
        <h3>&nbsp;&nbsp;&nbsp;&nbsp;名:</h3><input class="form-control"  id="username" name="username" type="text"  style="height:40px" value=""  placeholder="只能输入字母或数字,4-16个字符"/>
	</div>		
	<div class="input-group">
        <h3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;码:</h3><input class="form-control"  id="password" name="password" type="password" style="height:40px" value=""  placeholder="密码长度6-12位"/>
		<span class="input-group-btn">
			<INPUT class="btn btn-default" id="passwordeye" type="button" value="show/hide"">
        </span>
    </div>
	<div class="input-group">
        <h3>确认密码:</h3><input class="form-control"  id="password2" name="password2" type="password" style="height:40px" value=""/>
		<span class="input-group-btn">
			<INPUT class="btn btn-default" id="passwordeye2" type="button" value="show/hide"">
        </span>
	</div>     
	<div id="btn">
		<INPUT name="registerButton"  class="btn btn-primary" type="submit" id="Button" value="注册"  onclick="checkUserName()">
		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;	
		<a href="login.html"><INPUT  class="btn btn-primary" name="loginButton" id="Button" type="button" value="登录"></a>
	</div>
</form>
</div>
<div id="bottom">
	<div class="footer" style="color:white;">
     	Copyright &copy; 2013-2019 All Rights Reserved. 备案号:
    </div>
</div>
</body>
</html>

对应的 register.c

#include <stdio.h>
#include "cgic.h"
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <mysql/mysql.h>
#include <stdbool.h>

#define SQL_SIZE 256 

int cgiMain(void)
{
    char username[20];
    char password[20];
    char email[40];
	//回显信息到HTML网页cgiHeaderContentType("text/html");
    printf("<html>\n\n");
	printf("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\n");
	printf("<p>\n\n");
    
	if(cgiFormString("username", username, sizeof(username)) != cgiFormSuccess)
    {
        fprintf(stderr, "cgiFormString function username failed");
        //exit(-1);
    }
	printf("用户名:%s\n\n",username);
    printf("<br>\n\n");
	// password gateway server_ip dns subnet_mask dhcp error
	if(cgiFormString("password", password, sizeof(password)) != cgiFormSuccess)
    {
        fprintf(stderr, "cgiFormString function password failed");
        //exit(-1);
    }
	printf("密码:%s\n\n",password);
    printf("<br>\n\n");
/*
	if(cgiFormString("email", email, sizeof(email)) != cgiFormSuccess)
    {
        fprintf(stderr, "cgiFormString function email failed");
        //exit(-1);
    }
	printf("电子邮箱:%s\n\n",phone);
    printf("<br>\n\n");
*/

	/***  将用户信息写入MySQL数据库中  ***/ 
	//数据存储到数据库
	MYSQL* conn;
	bool isAutoCommit;
	
	// 初始化 MySQL
	conn = mysql_init(NULL);
    if(NULL == conn)
    {
        printf("errno:%d error:%s\n",mysql_errno(conn),mysql_error(conn));
        exit(-1);
    }
    
	char ip[16] = "127.0.0.1";
	char user[20] = "test";
	char passwd[20] = "test";
	char database[20] = "register";
	int port = 3306;

	// 尝试与运行在主机上的MySQL数据库引擎建立连接
	if(NULL == mysql_real_connect(conn,ip,user,passwd,database,port,NULL,0))
    {
        printf("---errno:%d error:%s\n\n",mysql_errno(conn),mysql_error(conn));
        exit(-1);
    }
	
	isAutoCommit = true;
	// 根据mysql的autocommit参数设置来决定是否自动提交
	mysql_autocommit(conn,isAutoCommit);

	// 设定数据库编码
	mysql_query(conn,"SET NAMES 'utf8'");
	mysql_query(conn,"SET CHARACTER SET utf8");
	mysql_query(conn,"SET CHARACTER_SET_RESULT = utf8");

    char cmd[SQL_SIZE];
	// 置字节字符串cmd的前SQL_SIZE个字节为零且包括‘\0’
    bzero(cmd, SQL_SIZE);
	// 创建user表
    // strcpy(cmd, "CREATE TABLE user(username varchar(20) PRIMARY KEY,password varchar(20));");

	// 将sql语句写入cmd变量
	sprintf(cmd, "INSERT INTO user values('%s', '%s');",username,password);

	printf("%s\n\n",cmd);

	// 向与指定的连接标识符关联的服务器中的当前活动数据库发送一条查询
	if(mysql_query(conn,cmd) != 0)
	{
		printf("errno:%d error:%s\n\n",mysql_errno(conn),mysql_error(conn));
		printf("<p>注册失败,请重新注册</p>\n\n");	
		sleep(1);
		printf("<meta http-equiv=Refresh content=1;URL=../register.html>\n");   	
	}
	//mysql_affected_rows(conn);

	printf("<p>注册成功</p>\n\n");	
	printf("<br>\n\n");
	printf("<p>您的用户名和密码为:</p>\n\n");	
	
	sprintf(cmd,"select * from user;");

	MYSQL_RES *res;
	MYSQL_ROW row;
	
	if(mysql_query(conn,cmd) != 0)
	{
		printf("errno:%d error:%s\n",mysql_errno(conn),mysql_error(conn));
		return -1;
	}
	
	int num_fields = mysql_field_count(conn);
	if(num_fields == 0)
	{
		printf("errno:%d error:%s\n",mysql_errno(conn),mysql_error(conn));
		return -1;	
	}
	
	res = mysql_store_result(conn);
	if(NULL == res)
	{
		printf("errno:%d error:%s\n",mysql_errno(conn),mysql_error(conn));
		return -1;
	}
	
	printf("<br>\n\n");
	printf("<br>\n\n");
	while((row = mysql_fetch_row(res)))
	{
		char arr[1000];
		int i = 0;
		for( ; i<num_fields; i++)
		{
			printf("%s ",row[i]);
		}
		printf("\n\n");
		printf("<br>\n\n");
	}
	
	mysql_free_result(res);

	sleep(1);

	printf("<meta http-equiv=Refresh content=1;URL=../login.html>\n");   

	return 0;
}

其余参考GitHub码云

常见错误

你的配置会影响网址,502什么错误也是配置或权限有问题导致的。
如:
502 Bad Gateway
The CGI was not CGI/1.1 compliant.
cgi_header: unable to find LFLF

1.可能是网址打错了(路径是否和配置文件对应)
2.配置有问题
3.权限没给足 chmod 777 test.cgi
4.代码本身有问题(先测测 cgi-test.cgi)

提示“保存文件”
在这里插入图片描述
是直接运行的网页,地址不对,改成 http://localhost:886/config.html 即可。

补充

文件上传

修改boa对单个上传文件大小的限制,src下的defines.h的SINGLE_POST_LIMIT_DEFAULT,单位 字节
前端post方式上传文件到后端 /var/www/cgi-bin 目录下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

upload.html
<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
	<title>upload</title>
	<script src="js/jquery-2.2.3.min.js"></script>
	<script src="js/jquery-ui.min.js"></script>
	<link type="text/css" href="css/jquery-ui.min.css" rel="stylesheet">
	<link href="css/bootstrap.min.css" rel="stylesheet">
	<script src="js/bootstrap.min.js"></script>
	<script>
		//文件上传ajax部分
		function uploadFile()
		{
			var fd = new FormData();
			fd.append("file", document.getElementById('file').files[0]);
			var xhr = new XMLHttpRequest();
			xhr.upload.addEventListener("progress", uploadProgress, false);
			xhr.addEventListener("load", uploadComplete, false);
			xhr.addEventListener("error", uploadFailed, false);
			xhr.addEventListener("abort", uploadCanceled, false);
			xhr.open("POST", "cgi-bin/upload.cgi"); //修改成自己的接口
			xhr.send(fd);
		}

		function uploadProgress(evt)
		{
			if (evt.lengthComputable)
			{
				//var percentComplete = Math.round(evt.loaded * 100 / evt.total);
				//document.getElementById('progressNumber').innerHTML =   percentComplete.toString() + '%';
			}
			else
			{
				//document.getElementById('progressNumber').innerHTML = 'unable to compute';
			}
		}

		function uploadComplete(evt)
		{
			/* 服务器端返回响应时候触发event事件*/
			alert(evt.target.responseText);
			document.getElementById('file').outerHTML = document.getElementById('file').outerHTML;
		}

		function uploadFailed(evt)
		{
			alert("There was an error attempting to upload the file.");
			document.getElementById('file').outerHTML = document.getElementById('file').outerHTML;
		}

		function uploadCanceled(evt)
		{
			alert("The upload has been canceled by the user or the browser dropped the connection.");
			document.getElementById('file').outerHTML = document.getElementById('file').outerHTML;
		}
	</script>
</head>

<body>
	<h2>目录权限,程序权限记得都给上</h2>
	<form method="post" enctype="multipart/form-data">
		<input type="file" name="file" id="file"/>
		<input type="button" value="上传" onclick="uploadFile();"/>
	</form>
</body>
</html>
upload.c
// 编译 gcc upload.c cgic.c -o upload.cgi
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include "cgic.h"

#define BufferLen 1024

int cgiMain(void)
{
	cgiFilePtr file;
	int targetFile = 0;
	mode_t mode;
	char name[128] = {};
	char fileNameOnServer[64] = {};
	char buf[1024] = {};
	char buf2[1024] = {};
	char contentType[1024] = {};
	char buffer[BufferLen];
	char *tmpStr = NULL;
	int size = 0;
	int got = 0, t = 0;

	cgiHeaderContentType("text/html");

	//取得html页面中file元素的值,应该是文件在客户机上的路径名
	if (cgiFormFileName("file", name, sizeof(name)) != cgiFormSuccess)
	{
		//fprintf(stderr,"could not retrieve filename\n");
		printf("could not retrieve filename\n");
		goto FAIL;
	}
	cgiFormFileSize("file", &size);
	//取得文件类型,不过本例中并未使用
	cgiFormFileContentType("file", contentType, sizeof(contentType));
	//目前文件存在于系统临时文件夹中,通常为/tmp,通过该命令打开临时文件。临时文件的名字与用户文件的名字不同,所以不能通过路径/tmp/userfilename的方式获得文件
	if (cgiFormFileOpen("file", &file) != cgiFormSuccess)
	{
		//fprintf(stderr,"could not open the file\n");
		printf("could not open the file\n");
		goto FAIL;
	}
	t = -1;
	//从路径名解析出用户文件名
	while (1)
	{
		tmpStr = strstr(name + t + 1, "//");
		if (NULL == tmpStr)
			tmpStr = strstr(name + t + 1, "/"); //if "//" is not path separator, try "/"
		if (NULL != tmpStr)
			t = (int)(tmpStr - name);
		else
			break;
	}
	strcpy(fileNameOnServer, name + t + 1);

	mode = S_IRWXU | S_IRGRP | S_IROTH;
	//在当前目录下建立新的文件,第一个参数实际上是路径名,此处的含义是在cgi程序所在的目录(当前目录))建立新文件
	snprintf(buf, 200, "/var/www/cgi-bin/%s", fileNameOnServer);

	targetFile = open(buf, O_RDWR | O_CREAT | O_TRUNC | O_APPEND, mode);
	if (targetFile < 0)
	{
		//fprintf(stderr,"could not create the new file,%s\n",fileNameOnServer);
		snprintf(buf2, 1000, "could not create the new file,%s\n", fileNameOnServer);
		printf(buf2);
		goto FAIL;
	}
	//从系统临时文件中读出文件内容,并放到刚创建的目标文件中
	while (cgiFormFileRead(file, buffer, BufferLen, &got) == cgiFormSuccess)
	{
		if (got > 0)
			write(targetFile, buffer, got);
	}
	cgiFormFileClose(file);
	close(targetFile);
	goto END;
FAIL:
	//fprintf(stderr,"Failed to upload");
	printf("Failed to upload\n");
	return 1;
END:
	snprintf(buf2, 1000, "File %s has been uploaded\n", fileNameOnServer);
	printf(buf2);
	// dos2unix filename (windows上传上来的文件换行不一样)
	return 0;
}

嵌入式web服务器boa框架的基础上, 使用C语言cgi, 或者Python脚本, 结合HTML + javascript + ajax 的嵌入式web系统的开发实例 html 中使用javascritp + ajax 从C语言生成的cgi文件的get, set 一些值. boa服务器的相关配置参数说明: http://www.cnblogs.com/liuweiqiang/p/3859130.html boa安装包文件名: boa-for-hi3516a.tar.gz boa.conf 文件的保存路径: cat /etc/boa/boa.conf boa可 执行文件的路径: /usr/local/bin/boa, 可以设置为: 系统启动的时候, 这个进程自动启动 boa.conf 文件的重要参数 保存html文件的目录 DocumentRoot /www 可以将这个目录, 设置为samb共享文件夹的目录, 方便修改调试 修改完成以后, 肯定要重启boa进程的 保存python脚本, 或者C语言cgi文件的目录 ScriptAlias /cgi-bin/ /var/www/cgi-bin/ 说明: cgi-bin/ 后面的斜杠, 一定要加上 可以将这个目录, 设置为samb共享文件夹的目录, 方便修改调试 修改完成以后, 肯定要重启boa进程的 html文件文件中, 调用python脚本的时候, 指定的路径, 需要有: /cgi-bin, 比如: var url = "/cgi-bin/getuser.py"; 这个是python 或者 var url = "/cgi-bin/output.cgi"; 这个是C语言 说明: 如果发现, html文件, 修改了, 可是在浏览器中, 查看html源代码的时候, 这个代码, 还是旧的, 那么可以通过清空"IE浏览器", "360浏览器"的浏览记录 以上, javascript 可以调用python 同样, 也可以调用C语言生成的cgi文件(其实, 就是可执行文件) C语言 + Html 例子 C语言 CGI实例 http://blog.csdn.net/ajrm0925/article/details/8810342 http://blog.csdn.net/liang890319/article/details/6277900 http://blog.csdn.net/gnefniu/article/details/42432657 上传文件: http://blog.csdn.net/yu_xiang/article/details/7996670 查找文件 find . -type f -name "boa.conf" -print -mount find . -type f -name "boa" -print -mount 四、嵌入式web服务器boa的配置和使用 嵌入式web服务器boa的配置文件为boa.conf, 在boa-0.94.13目录下面,复制该文件到文件 系统的/etc/boa目录下面,打开boa.conf,修改为如下内容: Port 80 User root Group root ErrorLog /dev/console AccessLog /dev/null ServerName SoftEmbed.com DocumentRoot /www DirectoryIndex index.html KeepAliveMax 1000 KeepAliveTimeout 10 MimeTypes /etc/mime.types DefaultType text/plain CGIPath /bin:/usr/bin:/usr/local/bin ScriptAlias /cgi-bin/ /www/cgi-bin/ 几个重要配置参数如下: DocumentRoot: 存放html文档的主目录; DirectoryIndex: 默认返回的html文档; ScriptAlias:cgi脚本虚拟路径对应的实际路径,/www/cgi-bin/为cgi脚本存放的实际路径; 其他配置选项的意义请参考相关资料。 复制boa可执行文件到/usr/sbin目录中, 启动boa进程 重新制作文件系统,系统启动后,在客户端浏览器上输入开发板的ip 地址,例如: http://192.168.0.218, 就可以看到显示的测试网页了,如下图所示 CGI getenv函数的参数详解: http://www.cnblogs.com/ser0632/p/5498228.html s = getenv("环境变量名"); 取得环境变量内容 putenv改变或增加环境变量 int putenv(const char * string); setenv(改变或增加环境变量) http://www.jb51.net/article/71940.htm
评论 38
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Love丶伊卡洛斯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值