声明:本文的代码部分为网上代码,但文章属作者原创。
最近在要使用到goahead上传下载功能,然后发现网上有不少上传文件的教程了,但是下载这块就不是讲的很详细,所以在这里大致讲一下。
虚拟机版本:ubuntu14.02
goahead版本:goahead-4.0.2
goahead文件下载需要添加的源码
首先我们需要在goahead.c文件中添加部分代码,代码如下:
1.声明部分
static char *websIndex; /* Default page name */
static char *websDocuments; /* Default Web page directory */
PUBLIC void split(char *src, const char *separator, char **dest, int *num)
{
char *pNext;
int count = 0;
if (src == NULL || strlen(src) == 0) return;
if (separator == NULL || strlen(separator) == 0) return;
pNext = strtok(src,separator);
while(pNext != NULL)
{
*dest++ = pNext;
++count;
pNext = strtok(NULL,separator);
}
*num = count;
}
PUBLIC char *getUrlLastSplit(char *s, const char * separator)
{
char *buf;
//char src[] = "C:\\\aaa\\Wildlife8888.wmv";
char *dest[64];
char *dest2[64];
int num = 0;
if (separator == NULL || strlen(separator) == 0)
return "";
split(s,separator,dest,&num);
if (num>1){
if (dest[num-1] == NULL) {
dest[num-1] = "";
}
buf = walloc(strlen(dest[num-1]) + 1);
strcpy(buf, dest[num-1]);
}else{
buf = walloc(strlen("") + 1);
strcpy(buf, "");
}
return buf;
}
//下载文件
static void fileWriteEvent(Webs *wp);
static void actionDownLoad(Webs *wp, char *path, char *query);
2.在goahead.c文件中的main函数中websServiceEvents(&finished);之前添加
websDefineAction("down", actionDownLoad);//下载文件来实现它
3.函数
static bool avolfileHandler(Webs *wp)
{
WebsFileInfo info;
char *tmp, *date;
ssize nchars;
int code;
char *pathfilename; //带路径的文件名
char *filenameExt; //文件扩展名
char *filename; //下载后保存的文件名
char *disposition; //临时保存 附件 标识
assert(websValid(wp));//确保路径的正确性
assert(wp->method);
assert(wp->filename && wp->filename[0]);
pathfilename = websGetVar(wp, "video", NULL);
if (pathfilename==NULL)
return 1;
//取文件名和扩展名
filename =sclone(getUrlLastSplit(sclone(pathfilename),"\\"));
filenameExt =sclone(getUrlLastSplit(sclone(filename),"."));
if (wp->ext) wfree(wp->ext);
wp->ext=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 !BIT_ROM
if (smatch(wp->method, "DELETE")) {
if (unlink(wp->filename) < 0) {
websError(wp, HTTP_CODE_NOT_FOUND, "Can't delete the URI");
} else {
/* No content */
websResponse(wp, 204, 0);
}
} else if (smatch(wp->method, "PUT")) {
/* Code is already set for us by processContent() */
websResponse(wp, wp->code, 0);
} else
#endif /* !BIT_ROM */
{
/*
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';
}
tmp = sfmt("%s/%s", wp->path, websIndex);
websRedirect(wp, tmp);
wfree(tmp);
return 1;
}
if (websPageOpen(wp, O_RDONLY | O_BINARY, 0666) < 0) {
#if BIT_DEBUG
if (wp->referrer) {
trace(1, "From %s", wp->referrer);
}
#endif
websError(wp, HTTP_CODE_NOT_FOUND, "Cannot open document for: %s", wp->path);
return 1;
}
if (websPageStat(wp, &info) < 0) {
websError(wp, HTTP_CODE_NOT_FOUND, "Cannot stat page for URL");
return 1;
}
code = 200;
if (wp->since && info.mtime <= wp->since) {
code = 304;
}
websSetStatus(wp, code);
websWriteHeaders(wp, info.size, 0);
// 为了下载文件时保存为真正的文件名称
disposition = 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 1;
}
websSetBackgroundWriter(wp, fileWriteEvent);
}
return 1;
}
static void avolfileClose()
{
wfree(websIndex);
websIndex = NULL;
wfree(websDocuments);
websDocuments = NULL;
}
//static WebsHash handlers = -1;
static void actionDownLoad(Webs *wp, char *path, char *query)
{
(*wp).route->handler->close = (*avolfileClose);
(*wp).route->handler->service =(*avolfileHandler);
(*wp).route->handler->service(wp);
}
static void fileWriteEvent(Webs *wp)
{
char *buf;
ssize len, wrote;
assert(wp);
assert(websValid(wp));
/*
Note: websWriteSocket may return less than we wanted. It will return -1 on a socket error.
*/
if ((buf = walloc(BIT_GOAHEAD_LIMIT_BUFFER)) == NULL) {
websError(wp, HTTP_CODE_INTERNAL_SERVER_ERROR, "Can't get memory");
return;
}
while ((len = websPageReadData(wp, buf, BIT_GOAHEAD_LIMIT_BUFFER)) > 0) {
if ((wrote = websWriteSocket(wp, buf, len)) < 0) {
break;
}
if (wrote != len) {
websPageSeek(wp, - (len - wrote), SEEK_CUR);
break;
}
}
wfree(buf);
if (len <= 0) {
websDone(wp);
}
}
在goahead-linux-static-me.h中添加上下面这部分代码
#ifndef BIT_GOAHEAD_LIMIT_BUFFER
#define BIT_GOAHEAD_LIMIT_BUFFER 8192
#endif
4.重新编译goahead,然后在终端中进入goahead可运行文件的目录,然后运行goahead。返回浏览器
输入假设我们开启的是0.0.0.0:8080端口
http://0.0.0.0:8080/action?video=/tmp/111.jpg // tmp是我们访问goahead的那个目录下的一个子目录
111.jpg是我们要下载的文件