将文件上传到C中的apache服务器(不带Web头)

时间:2015-04-28 12:26:48

标签: c apache file-upload webserver apache-modules

我正在开发webserver(Linux中的Apache 2.4)并尝试支持从客户端到服务器端的文件上传。 我成功地在服务器端接收文件,但是我在上传的文件内容中获得了额外的Web标题,我想省略它。例如,我在上传包含:

的example.txt时
I'm the file content!

在服务器端文件中我得到:

------WebKitFormBoundaryqbGGz0VOmz7CVPCF
Content-Disposition: form-data; name="file"; filename="example.txt"
Content-Type: application/octet-stream
I'm the file content!
------WebKitFormBoundaryqbGGz0VOmz7CVPCF--

实际文件是二进制文件,所以它应该包含没有添加数据的确切内容。

我使用了这些例子: mod_uploadmod_csv

我的服务器端代码是:

apr_bucket_brigade* bb;
apr_bucket* b;
int status = 0;
int end = 0;
char* fname = 0;
const char* buf;
apr_size_t bytes;
char buffer[512];
apr_file_t* tmpfile;

char* tmpname = apr_pstrdup(r->pool, "/tmp/tmp-upload.XXXXXX") ;

if ( apr_file_mktemp(&tmpfile, tmpname, KEEPONCLOSE, r->pool) != APR_SUCCESS ) {
    ap_remove_input_filter(r->input_filters) ;
}

apr_pool_cleanup_register(r->pool, tmpfile, (void*)apr_file_close, apr_pool_cleanup_null) ;
bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);

do {
    status = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, APR_BLOCK_READ, BLOCKSIZE) ;
    if ( status == APR_SUCCESS ) {
        for (b = APR_BRIGADE_FIRST(bb) ; b != APR_BRIGADE_SENTINEL(bb) ; b = APR_BUCKET_NEXT(b)) {
            if (APR_BUCKET_IS_EOS(b)) {
                end = 1;
                break;
            }
            else if (apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ) == APR_SUCCESS) {
                apr_file_write(tmpfile, buf, &bytes);
                char* x = apr_pstrndup(r->pool, buf, bytes);
                if (fname)
                    fname = apr_pstrcat(r->pool, fname, x, NULL);
                else
                    fname = x;
            }
            else {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Bucket read error") ;
            }
        }
    }
    else {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Brigade error") ;
    }
    apr_brigade_cleanup(bb);
} while ( !end && status == APR_SUCCESS );
apr_brigade_destroy(bb);

return OK;

如何更改代码以避免结果文件内容中的冗余标头/任何其他方式(/方法)来获取服务器中的文件?

谢谢!

2 个答案:

答案 0 :(得分:1)

http://apache.webthing.com/mod_upload/mod_upload.c

这里

static void set_header(upload_ctx* ctx, const char* data) 

此功能添加标题。如果您不想要标题,则不要在该文件中调用此函数。

答案 1 :(得分:0)

所以...我的解决方案是手动删除这些前缀和后缀标题。 它可能会帮助将来的某个人:

int getPrefixHeaderLength(const char* buf) {
    int rows = 0;
    int counter = 0;
    char* ret = buf;

    if (buf == NULL)
        return 0;

    while (*ret != 0 && rows < 4) {
        if (*ret == '\n')
            rows++;

        ret++;
        counter++;
    }

    return counter;
}

/* example buf: "... filename="example.txt" "  */
void getFilename(const char* buf, char* filename)
{
    char* pEnd = NULL;
    char *pFilename = strstr(buf,"filename");
    pFilename += 10;
    pEnd = strchr(pFilename,'"');
    snprintf(filename,pEnd-pFilename+1,"%s",pFilename);
}

apr_bucket_brigade* bb;
apr_bucket* b;
int status = 0;
int end = 0;
char* fname = 0;
const char* buf;
apr_size_t bytes;
apr_size_t totalBytes = 0;
char buffer[512];
apr_file_t* tmpfile;
const char* ctype = apr_table_get(r->headers_in, "file-0") ;
int prefixFlag = 1;
int counter = 0;
apr_off_t offsetIndex = 0;
char filename[512];

char* tmpname = apr_pstrdup(r->pool, "/tmp/tmp-upload.XXXXXX") ;

if ( apr_file_mktemp(&tmpfile, tmpname, KEEPONCLOSE, r->pool) != APR_SUCCESS ) {
    ap_remove_input_filter(r->input_filters) ;
}

apr_pool_cleanup_register(r->pool, tmpfile, (void*)apr_file_close, apr_pool_cleanup_null) ;

bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);

do {
    status = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, APR_BLOCK_READ, BLOCKSIZE) ;
    if ( status == APR_SUCCESS ) {
        for (b = APR_BRIGADE_FIRST(bb) ; b != APR_BRIGADE_SENTINEL(bb) ; b = APR_BUCKET_NEXT(b)) {
            if (APR_BUCKET_IS_EOS(b)) {
                end = 1;
                break;
            }
            else if (apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ) == APR_SUCCESS) {
                int prefixHeaderLength = 0;
                apr_size_t sizeToWrite;

                if (prefixFlag) {
                    if (bytes == 1) {
                        continue;
                    }

                    prefixHeaderLength = getPrefixHeaderLength(buf);
                    prefixFlag = 0;
                    getFilename(buf,filename);
                    ap_rprintf(r, "\"filename\":\"%s\",",filename);
                }
                //ap_rprintf(r, "\"counter%d\":%d,",counter,bytes);
                sizeToWrite = bytes - prefixHeaderLength;
                apr_file_write(tmpfile, buf+prefixHeaderLength, &sizeToWrite);
                //ap_rprintf(r, "\"write%d\":%d,",counter,sizeToWrite);
                totalBytes += bytes;
            }
            else {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Bucket read error") ;
            }
        }
    }
    else {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Brigade error") ;
    }
    apr_brigade_cleanup(bb);
    counter++;
} while ( !end && status == APR_SUCCESS );

counter = 0;

while (counter < 2) {
    char c;
    offsetIndex = -2L;
    apr_file_seek(tmpfile,SEEK_CUR, &offsetIndex);
    apr_file_getc(&c,tmpfile);

    if (c == '\r')
        counter++;
}

apr_file_trunc(tmpfile,offsetIndex);
ap_rprintf(r, "\"size\":%d}",totalBytes);

apr_brigade_destroy(bb);
return OK;