用C语言将文件上载到apache服务器(不带web头)
我正在开发webserver(linux中的Apache2.4),并尝试支持从客户端到服务器端的文件上传。 我成功地在服务器端接收到了文件,但我在上传的文件内容中得到了一个额外的web头,我想省略它。例如,我在上传example.txt时,其中包含:用C语言将文件上载到apache服务器(不带web头),c,apache,file-upload,webserver,apache-modules,C,Apache,File Upload,Webserver,Apache Modules,我正在开发webserver(linux中的Apache2.4),并尝试支持从客户端到服务器端的文件上传。 我成功地在服务器端接收到了文件,但我在上传的文件内容中得到了一个额外的web头,我想省略它。例如,我在上传example.txt时,其中包含: I'm the file content! 在服务器端文件中,我得到: ------WebKitFormBoundaryqbGGz0VOmz7CVPCF Content-Disposition: form-data; name="file"; f
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--
具有的实际文件是二进制文件,因此它应该包含准确的内容,而不添加数据
我用了这些例子:
和
我的服务器端代码是:
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;
如何更改代码以避免结果文件内容中的冗余头/以任何其他方式(/方法)在服务器中获取文件
谢谢
这里
此函数用于添加标题。如果不需要标题,则不要在该文件中调用此函数。因此。。。我的解决方案是手动删除这些前缀和后缀标题。 它可能会在将来帮助某人:
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;
int getPrefixHeaderLength(常量字符*buf){
int行=0;
int计数器=0;
char*ret=buf;
如果(buf==NULL)
返回0;
而(*ret!=0&&rows<4){
如果(*ret=='\n')
行++;
ret++;
计数器++;
}
返回计数器;
}
/*示例buf:“…filename=“example.txt”*/
void getFilename(const char*buf,char*filename)
{
char*pEnd=NULL;
char*pFilename=strstr(buf,“文件名”);
pFilename+=10;
pEnd=strchr(pFilename,“”);
snprintf(文件名,pEnd pFilename+1,“%s”,pFilename);
}
apr_bucket_Batch*bb;
apr_bucket*b;
int status=0;
int end=0;
char*fname=0;
常量字符*buf;
apr\u大小\u t字节;
apr_size_t totalBytes=0;
字符缓冲区[512];
apr_文件*tmpfile;
const char*ctype=apr_table_get(r->headers_in,“file-0”);
int prefixFlag=1;
int计数器=0;
apr_off_t offsetIndex=0;
字符文件名[512];
char*tmpname=apr\pstrdup(r->pool,“/tmp/tmp upload.XXXXXX”);
if(apr\u file\u mktemp(&tmpfile,tmpname,KEEPONCLOSE,r->pool)!=apr\u成功){
ap_移除输入_过滤器(r->输入_过滤器);
}
apr\u pool\u cleanup\u寄存器(r->pool,tmpfile,(void*)apr\u文件\u close,apr\u pool\u cleanup\u null);
bb=apr\u BACKUP\u create(r->pool,r->connection->bucket\u ALOC);
做{
状态=ap\U get\U BATTING(r->input\U过滤器、bb、ap\U MODE\U READBYTES、APR\U BLOCK\U READ、BLOCKSIZE);
如果(状态==APR\U成功){
对于(b=APR_旅_首个(bb);b!=APR_旅_哨兵(bb);b=APR_桶_下一个(b)){
如果(APR_BUCKET_是EOS(b)){
结束=1;
打破
}
else if(apr\u bucket\u read(b,&buf,&bytes,apr\u BLOCK\u read)=apr\u SUCCESS){
int prefixHeaderLength=0;
apr_size_t size写入;
if(prefixFlag){
如果(字节==1){
继续;
}
prefixHeaderLength=getPrefixHeaderLength(buf);
prefixFlag=0;
getFilename(buf,filename);
ap_rprintf(r,“\”文件名“:\%s\”,“,文件名);
}
//ap_rprintf(r,“\”计数器%d\:%d,”,计数器,字节);
sizeToWrite=字节-prefixHeaderLength;
apr文件写入(tmpfile、buf+前缀头长度和大小写入);
//ap\u rprintf(r,“\”写入%d\”:%d,”,计数器,大小写入);
totalBytes+=字节;
}
否则{
ap_log_rerror(APLOG_标记,APLOG_错误,0,r,“存储桶读取错误”);
}
}
}
否则{
ap_日志错误(APLOG_标记,APLOG_错误,0,r,“旅错误”);
}
apr_旅_清理(bb);
计数器++;
}而(!end&&status==APR\u SUCCESS);
计数器=0;
while(计数器<2){
字符c;
offsetIndex=-2L;
apr文件搜索(TMP文件、搜索当前和偏移索引);
apr\u文件\u getc(&c,tmpfile);
如果(c=='\r')
计数器++;
}
apr文件(TMP文件,偏移索引);
ap_rprintf(r,“\”size\:%d}”,总字节数);
apr_旅_销毁(bb);
返回OK;
我没有使用mod_upload.c(我试过了,但没用),我只是从那里复制了一些代码(你在上面看到的代码),所以我不打电话来设置_头
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;