首页 > 技术文章 > goahead下载文件

sun-tbs 2018-10-30 15:24 原文

声明:本文的代码部分为网上代码,但文章属作者原创。

最近在要使用到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是我们要下载的文件

 

推荐阅读