Linux下goahead3.3.6的移植以及文件上传下载示例

#开源库下载

下载地址
https://embedthis.com/goahead/download.html

在下载地址中可以看到说明
Source Code Repository
To access the GoAhead source code at GitHub, see: GitHub GoAhead Repository.
To download source code for specific versions, see: GoAhead Releases.
分别是两个地址
github的托管地址 https://github.com/embedthis/goahead
下载之前不同版本的地址 https://github.com/embedthis/goahead/releases

当前能够看到的最新的版本是v3.6.5
并且可以依次往下看到版本有
2017-06-10 v3.6.5
2017-06-10 v3.6.4
2016-06-03 v3.6.3

2012-06-28 v2.5.0

我随机下载了 3.3.6 版本;

#开源库编译

$ tar -zxvf goahead-3.3.6.tar.gz 
$ cd goahead-3.3.6/
$ make CC=arm-none-linux-gnueabi-gcc ARCH=arm

编译完成后提示

You can now install via "sudo make ARCH=arm CC=arm-none-linux-gnueabi-gcc install" or run GoAhead via: "sudo make run"
To run locally, put linux-arm-default/bin in your path

说明已经编译成功;
进入目录 goahead-3.3.6/build/linux-arm-default/bin
看到了编译出来的嵌入式可执行文件 goahead 已经相关的库文件
ca.crt goahead goahead-test gopass libest.so libgo.so

其中 goahead 可以测试相关的get方法请求;
goahead-test 则有相关的post请求,并且有文件上传的例程;

编译过程中如果需要看到编译语句,可以使用 SHOW=1

$ make CC=arm-none-linux-gnueabi-gcc ARCH=arm SHOW=1
$ make clean CC=arm-none-linux-gnueabi-gcc ARCH=arm SHOW=1

添加断点调试 (-g) :

$ make CC='arm-none-linux-gnueabi-gcc -g' ARCH=arm SHOW=1

可执行程序goahead 是从 goahead-3.3.6/src/goahead.c 的 MAIN() 函数开始执行的;
goahead-test 是从 goahead-3.3.6/test/test.c 的 MAIN() 函数开始;

#开源库使用
在嵌入式 开发板上执行生成的goahead可执行文件

/mnt/test # ./goahead -v web 192.168.1.44:80
src/goahead.c(main)
goahead: 1: This system does not have IPv6 support
goahead: 2: Configuration for Embedthis GoAhead
goahead: 2: ---------------------------------------------
goahead: 2: Version:            3.3.6
goahead: 2: BuildType:          Debug
goahead: 2: CPU:                arm
goahead: 2: OS:                 linux
goahead: 2: Host:               192.168.1.44
goahead: 2: Directory:          /mnt/test
goahead: 2: Documents:          web
goahead: 2: Configure:          me -d -q -platform linux-x86-default -configure . -with est -gen make
goahead: 2: ---------------------------------------------
goahead: 2: Started http://192.168.1.44:80

问题1
/mnt/goahead-3.3.6/build/linux-arm-default/bin # ./goahead
goahead: 0: Cannot get host address for host sun5i: errno 11
goahead: 0: Cannot initialize server. Exiting.

修改代码 src/http.c
函数 static int setLocalHost()

	#if VXWORKS
	...
	#elif ECOS
	...
	#elif TIDSP
	...
	#elif MACOSX
	...
	#else
	{
		struct hostent  *hp;
		//if ((hp = gethostbyname(host)) == NULL) {
		//    error("Cannot get host address for host %s: errno %d", host, errno);
		//    return -1;
		// }
		//memcpy((char*) &intaddr, (char *) hp->h_addr_list[0], (size_t) hp->h_length);
		//ipaddr = inet_ntoa(intaddr);
		int sockfd;   
		struct sockaddr_in sin;   
		struct ifreq ifr;         
		sockfd = socket(AF_INET, SOCK_DGRAM, 0);      
		if (sockfd == -1)   {             
			return -1;            
		}         
		strncpy(ifr.ifr_name, "eth0", IFNAMSIZ);    // 指定网卡  
		ifr.ifr_name[IFNAMSIZ - 1] = 0;       
		if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0)    {             
			return -1;    
		}     
		memcpy(&sin, &ifr.ifr_addr, sizeof(sin));     
		ipaddr=inet_ntoa(sin.sin_addr); 
		
		websSetIpAddr(ipaddr);
		websSetHost(ipaddr);
	}
	#endif

问题2
/mnt/goahead-3.3.6/build/linux-arm-default/bin # ./goahead
goahead: 0: Cannot open config file route.txt
goahead: 0: Cannot initialize server. Exiting.

拷贝 src/route.txt 到 build/linux-arm-default/bin/

问题3
/mnt/goahead-3.3.6/build/linux-arm-default/bin # ./goahead
goahead: 0: Cannot open config file auth.txt
goahead: 0: Cannot load auth.txt
拷贝 src/auth.txt 到 build/linux-arm-default/bin/

拷贝网页并进行访问
新建目录 build/linux-arm-default/web/
拷贝 test/web/index.html 到 build/linux-arm-default/web/目录
直接网页上输入开发板的IP地址 192.168.1.123 即可看到
这里写图片描述
这里我修改了一下网页的显示文字

使用get方法访问数据
修改 src/auth.c 的 loginServiceProc 函数;

static void loginServiceProc(Webs *wp)
{
    WebsRoute   *route;

    assert(wp);
    route = wp->route;
    assert(route);
    printf("%s(%s:%d)%s, %s\n", __FILE__, __FUNCTION__, __LINE__, 
	websGetVar(wp, "username", ""), websGetVar(wp, "password", ""));
    if (websLoginUser(wp, websGetVar(wp, "username", ""), websGetVar(wp, "password", ""))) {
        /* If the application defines a referrer session var, redirect to that */
        char *referrer;
        if ((referrer = websGetSessionVar(wp, "referrer", 0)) != 0) {
            websRedirect(wp, referrer);
        } else {
            websRedirectByStatus(wp, HTTP_CODE_OK);
        }
        websSetSessionVar(wp, "loginStatus", "ok");
    } else {
        if (route->askLogin) {
            (route->askLogin)(wp);
        }
        websSetSessionVar(wp, "loginStatus", "failed");
        //websRedirectByStatus(wp, HTTP_CODE_UNAUTHORIZED);
        websWrite(wp,(char *)"I am test");
        // websRedirectByStatus(wp, HTTP_CODE_OK);
        websDone(wp);
    }
}

在浏览器中访问开发板上的接口

这里写图片描述

其中这里访问了bbbb/目录,因为修改了 goahead-3.3.6/build/linux-arm-default/bin/route.txt

#   For legacy GoAhead applications using /goform
#route uri=/goform handler=action
route uri=/bbbb handler=action

#GET请求和文件上传下载

get请求和文件上传

// $ export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
// $ arm-none-linux-gnueabi-gcc main.c -L ./ -lgo -lest
// $ ./a.out
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include "goahead.h"

#define wfree(p) if (p) { free(p); } else

static int finished = 0;
static void initPlatform();
static void ShowString(Webs *wp);
static void uploadTest(Webs *wp, char *path, char *query);

int main(){
	printf("starting...\n");
	char *route = (char*)"route.txt";
    char *auth = (char*)"auth.txt";
	char *documents = (char*)"web";
	
	initPlatform();
    if (websOpen(documents, route) < 0) {
        error("Cannot initialize server. Exiting.");
        return -1;
    }
    if (websLoad(auth) < 0) {
        error("Cannot load %s", auth);
        return -1;
    }
	websDefineAction("showString", ShowString);
	websDefineAction("uploadTest", uploadTest);
	char *endpoints = (char*)sclone((char*)"http://*:80,https://*:443");
	char *tok;
	char *endpoint;
	printf("(%d)\n", __LINE__);
	for (endpoint = stok(endpoints, ", \t", &tok); endpoint; endpoint = stok(NULL, ", \t,", &tok)) {
		printf("(%d)\n", __LINE__);
		if (websListen(endpoint) < 0) {
			return -1;
		}
		printf("(%d)\n", __LINE__);
	}
	printf("(%d)\n", __LINE__);
	wfree(endpoints);
	/
	if (websGetBackground()) {
        if (daemon(0, 0) < 0) {
            error("Cannot run as daemon");
            return -1;
        }
    }
	
    websServiceEvents(&finished);
	printf("Instructed to exit");
    websClose();
	return 0;
}

static void sigHandler(int signo){
	printf("(%s:%d)\n", __FUNCTION__, __LINE__);
    finished = 1;
}

static void initPlatform(){
	printf("(%s:%d)\n", __FUNCTION__, __LINE__);
    signal(SIGTERM, sigHandler);
    signal(SIGKILL, sigHandler);
    signal(SIGPIPE, SIG_IGN);
}

static void ShowString(Webs *wp){
    WebsRoute *route;
	char result[64];
    assert(wp);
    route = wp->route;
    assert(route);
	sprintf(result, "I am ShowString : %s", websGetVar(wp, "str", ""));
	websWrite(wp,result);
	websDone(wp);
}

static void uploadTest(Webs *wp, char *path, char *query)
{
    WebsKey         *s;
    WebsUpload  *up;
    char            *upfile;

    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);
    websWriteHeader(wp, "Content-Type", "text/plain");
    websWriteEndHeaders(wp);
    if (scaselessmatch(wp->method, "POST")) {
        for (s = hashFirst(wp->files); s; s = hashNext(wp->files, s)) {
            up = s->content.value.symbol;
			websWrite(wp, "TEST : 2017-8-10 14:06:04\r\n");
            websWrite(wp, "FILE: %s\r\n", s->name.value.string);
            websWrite(wp, "FILENAME=%s\r\n", up->filename);
            websWrite(wp, "CLIENT=%s\r\n", up->clientFilename);
            websWrite(wp, "TYPE=%s\r\n", up->contentType);
            websWrite(wp, "SIZE=%d\r\n", up->size);
            //upfile = sfmt("%s/tmp/%s", websGetDocuments(), up->clientFilename);
            upfile = sfmt("/tmp/%s", up->clientFilename);
            rename(up->filename, upfile);
            websWrite(wp, "UPFILE=%s\r\n", upfile);
            wfree(upfile);
        }
        websWrite(wp, "\r\nVARS:\r\n");
        for (s = hashFirst(wp->vars); s; s = hashNext(wp->vars, s)) {
            websWrite(wp, "%s=%s\r\n", s->name.value.string, s->content.value.string);
        }
    }
    websDone(wp);
}

/*
#
# 其中用的接口来自于 libgo.so
# websOpen
# websLoad
# sclone
# stok
# websListen
# websGetBackground
# websServiceEvents
# websClose
#
*/

这里写图片描述

文件上传接口

这里写图片描述
(直接使用自带的 goahead-3.3.6/test/web/upload/upload.html,拷贝到同级目录后使用)

上传完成之后,页面自动跳转显示(文件上传到开发板的 /tmp/ 目录下,由变量 upfile 决定)

TEST : 2017-8-10 14:06:04
FILE: file
FILENAME=/tmp/tmp-0.tmp
CLIENT=test.txt
TYPE=text/plain
SIZE=3
UPFILE=/tmp/test.txt

VARS:
HTTP_CONNECTION=keep-alive
HTTP_CONTENT_LENGTH=481
HTTP_CACHE_CONTROL=max-age=0
FILE_FILENAME_file=/tmp/tmp-0.tmp
UPLOAD_DIR=/tmp
HTTP_ACCEPT_ENCODING=gzip, deflate
HTTP_ORIGIN=http://192.168.1.123
Address=ddd
FILE_SIZE_file=3
HTTP_CONTENT_TYPE=multipart/form-data; boundary=----WebKitFormBoundary5gPnTrFrUlfqmM73
HTTP_REFERER=http://192.168.1.123/upload.html
HTTP_ACCEPT=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Name=abc
HTTP_ACCEPT_LANGUAGE=zh-CN,zh;q=0.8
MAX_FILE_SIZE=30000
HTTP_UPGRADE_INSECURE_REQUESTS=1
FILE_CLIENT_FILENAME_file=test.txt
HTTP_HOST=192.168.1.123
HTTP_USER_AGENT=Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
FILE_CONTENT_TYPE_file=text/plain

文件下载

// 开始下载 192.168.8.41/action/down?video=\UserDev\ip.dat
static void actionDownLoad(Webs *wp, char *path, char *query);

int main(){
	// 省略很多
	websDefineAction("down", actionDownLoad);
}


static void actionDownLoad(Webs *wp, char *path, char *query){
	//(*wp).route->handler->close = (*avolfileClose);
	//(*wp).route->handler->service = (*avolfileHandler);
	//(*wp).route->handler->service(wp);
	
	WebsHandlerProc service = (*wp).route->handler->service; 
	(*wp).route->handler->close = (*avolfileClose);
	(*wp).route->handler->service =(*avolfileHandler); 
	(*wp).route->handler->service(wp); 
	(*wp).route->handler->service= service; 
}

static void avolfileClose(){
	//wfree(websIndex);
	//websIndex = NULL;
	//wfree(websDocuments);
	//websDocuments = NULL;
}


static bool avolfileHandler(Webs *wp){
	WebsFileInfo    info;
	char *tmp, *date;
	ssize nchars;
	int code;

	char* pathfilename; //带路径的文件名 用于找到对应的文件
	char* filenameExt; //文件扩展名 用于 设置 MIME类型
	char* filename; //文件名 用于下载后保存的文件名称
	char* disposition; //临时保存 附件 标识
	
	assert(websValid(wp));
	assert(wp->method);
	assert(wp->filename && wp->filename[0]);

	// 取download.lua?video=C:\aaa.wmv 中的 C:\aaa.wmv
	pathfilename = websGetVar(wp, "video", NULL);
	if (pathfilename==NULL)
		return true;

	//取文件名和扩展名
	filename =sclone(getUrlLastSplit(sclone(pathfilename),"\\"));
	filenameExt =sclone(getUrlLastSplit(sclone(filename),"."));
	
	if (wp->ext) wfree(wp->ext);
 
	wp->ext=(char*)walloc(1+strlen(filenameExt)+1);
	sprintf(wp->ext,".%s",sclone(filenameExt));
	free(filenameExt);
	filenameExt=NULL;

	if (wp->filename) {
		wfree(wp->filename);
	}
	wp->filename=sclone(pathfilename);

	if (wp->path) {
		wfree(wp->path);
	}
	wp->path=sclone(pathfilename);
    
        //If the file is a directory, redirect using the nominated default page
        if (websPageIsDirectory(wp)) {
            nchars = strlen(wp->path);
            if (wp->path[nchars - 1] == '/' || wp->path[nchars - 1] == '\\') {
                wp->path[--nchars] = '\0';
            }
	    char* websIndex = "testdownload";
            tmp = sfmt("%s/%s", wp->path, websIndex);
            websRedirect(wp, tmp);
            wfree(tmp);
            return true;
        }
        if (websPageOpen(wp, O_RDONLY | O_BINARY, 0666) < 0) {
            websError(wp, HTTP_CODE_NOT_FOUND, "Cannot open document for: %s", wp->path);
            return true;
        }
        if (websPageStat(wp, &info) < 0) {
            websError(wp, HTTP_CODE_NOT_FOUND, "Cannot stat page for URL");
            return true;
        }
        code = 200;
        if (wp->since && info.mtime <= wp->since) {
            code = 304;
        }
        websSetStatus(wp, code);
        websWriteHeaders(wp, info.size, 0);

	//浏览器下载文件时的文件名 
	disposition = (char*)walloc(20+strlen(filename)+1);
	sprintf(disposition,"attachment;filename=%s",sclone(filename));
	websWriteHeader(wp, "Content-Disposition", sclone(disposition));
	free(filename);
	free(disposition);
	filename=NULL;
	disposition=NULL;

        if ((date = websGetDateString(&info)) != NULL) {
            websWriteHeader(wp, "Last-modified", "%s", date);
            wfree(date);
        }
        websWriteEndHeaders(wp);

        //All done if the browser did a HEAD request
        if (smatch(wp->method, "HEAD")) {
            websDone(wp);
            return true;
        }
        websSetBackgroundWriter(wp, fileWriteEvent);
	return true;
}

文件下载例程来自:
http://blog.csdn.net/china_boys/article/details/8710450
http://download.csdn.net/download/china_boys/5173588#comment

/demo目录下需要用到的库文件以及配置文件

auth.txt 	est.h 		goahead.h 	js.h
libest.so 	libgo.so 	main.c 		me.h
osdep.h 	route.txt

上传过大文件的时候,会直接出现找不到接口的网页报错;
修改上传文件的限制:
src/http.c/parseHeaders()

//if (wp->rxLen > ME_GOAHEAD_LIMIT_POST) {
if (wp->rxLen > ME_GOAHEAD_LIMIT_UPLOAD) {
	websError(wp, HTTP_CODE_REQUEST_TOO_LARGE | WEBS_CLOSE, "Too big");
	return;
}

其中
#define ME_GOAHEAD_LIMIT_POST 16384
#define ME_GOAHEAD_LIMIT_UPLOAD 204800000

这里直接用 ME_GOAHEAD_LIMIT_UPLOAD 替换掉原来的 ME_GOAHEAD_LIMIT_POST;
重新更新应用程序的动态库 libest.solibgo.so 实现更大文件的上传;

实际运行时别漏掉添加动态库的搜索路径

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Maven是一个用于构建和管理Java项目的开源工具。Maven的下载可以通过官方网站或者其他镜像站点进行。 要下载Maven 3.3.6版本,首先需要访问Apache Maven官方网站(https://maven.apache.org)。在该网站上,可以找到Maven的各个版本以及相关的文档和帮助。 在官方网站的下载页面上,可以找到Maven 3.3.6的下载链接。点击该链接将跳转到下载页面,可以选择适合自己操作系统的二进制压缩包进行下载。 除了官方网站,还可以通过其他镜像站点进行Maven的下载。这些镜像站点通常是为了提供更快的下载速度和更好的用户体验而创建的。在这些镜像站点上,也可以找到Maven 3.3.6的下载链接。 下载完成后,解压缩二进制压缩包到本地文件系统中的一个目录。然后,需要设置系统环境变量,将Maven的bin目录添加到系统的PATH变量中,这样就可以在命令行中直接使用Maven命令。 完成以上步骤后,可以在命令行中输入"mvn -version"命令来验证Maven的安装是否成功。 总的来说,Maven 3.3.6的下载相对简单,只需访问官方网站或其他镜像站点,并选择适合自己操作系统的压缩包进行下载下载完成后,解压缩并设置环境变量,即可使用Maven进行项目构建和管理。 ### 回答2: Maven是一个开源的项目管理和构建工具,用于管理Java项目的依赖关系和构建过程。Maven能够自动化地将项目的源代码编译、测试和打包,并管理项目所需的各种依赖库。 要下载Maven 3.3.6,可以按照以下步骤进行: 1. 打开Maven官方网站(https://maven.apache.org)。 2. 在网站的主页上,找到"Download"(下载)菜单并点击。 3. 在下载页面上,找到"Maven 3.3.6"的链接并点击。 4. 在接下来的页面上,可以看到一系列可供下载的文件。根据你的操作系统选择适合的安装包,如Windows、Mac或Linux。 5. 点击选择的安装包链接,即可开始下载。 6. 下载完成后,双击运行安装程序,并按照指示完成安装过程。注意,安装Maven可能需要管理员权限。 7. 安装完成后,打开命令行终端(或控制台)。 8. 输入"mvn -version"命令,如果显示了Maven的版本号(如3.3.6),则表示安装成功,可以开始使用了。 总结:下载Maven 3.3.6可以通过官方网站下载相应的安装包,然后按照安装程序的指示完成安装。安装成功后,可以在命令行终端中输入"mvn -version"命令,验证安装是否成功。Maven 3.3.6是一个比较常用的版本,可以帮助开发人员更方便地管理和构建Java项目。 ### 回答3: 要下载Maven 3.3.6,请按以下步骤操作: 1. 首先,打开您的网页浏览器,然后转到Apache Maven的官方网站。 2. 在页面的导航栏上,找到“Download”(下载)选项,并点击它。 3. 在下载页面上,您会看到不同版本的Maven可供选择。向下滚动,直到找到"Maven 3.3.6" 的下载链接。 4. 点击“Maven 3.3.6”下载链接,将自动开始下载Maven 3.3.6的二进制文件。 5. 下载完成后,您可以在您设置的目录中找到下载的文件。解压缩下载的文件,您就可以使用Maven 3.3.6了。 总结来说,开始下载Maven 3.3.6只需打开官方网站,找到相应版本的下载链接,完成下载后解压缩即可使用。希望这个回答对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值