一步步DIY: OSM-Web服务器(八) 使用 C FCGI 返回瓦片并登记下载

      卫星图片没有相应的mod_tile可以使用,故而需要我们自己来实现。最简单的方法,就是利用 libfcgi-dev 来写一个C的web-service,通过http://...//satile.fcgi?nRow=row&nCol=col&nLevel=lev 来下载,同时,对不在本地缓存内的瓦片,去网上下载。网上的下载程序不在fcgi里实现了,那样比较重量。可以把需要下载的瓦片登记下来,交给后台的下载器去下载。

      FCGI的核心是返回PNG图片,也就是用 image/PNG 作为头,后面跟着二进制流。返回PNG看似简单,着实调试了很久,原因就是头部那个该死的\n\n换行,以前是一个\n,结果不行。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcgi_stdio.h>
extern unsigned char bufempty [3531];

bool regisit_dbtask(int nLevel,int  nCol ,int   nRow )
{
    bool succeeded = false;
    char buffm[4096];
    sprintf(buffm,"/media/sf_tiles/satellite/%d/%d/%d.png",nLevel,nCol,nRow);

    FILE * fp = fopen(buffm,"rb");
    if (fp)
    {
        fseek (fp,0,SEEK_END);
        long nLen = ftell(fp);
        fseek (fp,0,SEEK_SET);
        if (nLen<=1024*1024)
        {
            unsigned char * pBuf = new unsigned char[nLen];
            fread(pBuf,nLen,1,fp);
            fwrite(pBuf,nLen,1,stdout);
            delete [] pBuf;
        }
        fclose(fp);
    }
    else
   {
       fwrite(bufempty,3531,1,stdout);
       FILE * foPut = fopen ("/media/sf_tiles/satellite.txt","a+");
       if (foPut )

       {
           fseek(foPut,0,SEEK_END);
           fprintf(foPut,"%d,%d,%d\n",nLevel,nCol,nRow);
           fclose(foPut);
       }
   }

    return succeeded;
}


int main(void)

{

    while (FCGI_Accept() >= 0)
    {
        char * rawdata = getenv("QUERY_STRING");
        //char * server_name = getenv("SERVER_NAME");
        int nLevel=0, nCol=0, nRow = 0;

        printf("Content-type: image/png\n\n");
        fflush(stdout);
        if (rawdata)
        {
            int nLen = strlen(rawdata);
            char * data = new char [nLen+1];
            strcpy (data,rawdata);
            char * pStrLevel = 0, * pStrCol = 0, * pStrRow = 0;
            char * tmp = 0;
            tmp = strstr(data,"nLevel=");
            if (tmp)
                 pStrLevel = tmp;
            tmp = strstr(data,"nRow=");
            if (tmp)
                pStrRow = tmp;
            tmp = strstr(data,"nCol=");
            if (tmp)
                pStrCol = tmp;

            if (pStrLevel&&      pStrCol    &&    pStrRow )
            {
                for (int i=0;i<nLen;i++)
                    if (data[i]=='?'||data[i]=='&')
                        data[i] = 0;
                nLevel =    atoi(pStrLevel +7);
                nCol =  atoi(pStrCol+5);
                nRow =      atoi(pStrRow   +5);
               delete [] data;
            }
            else
            {
                printf("<p>Error! At least Missing para nRow, nCol ,nLevel.</p>\r\n");
                delete [] data;
                continue;
            }

        }

        if (nLevel<0 || nLevel>18)
        {
            printf("<p>Error nLevel! nLevel must between 0~18.</p>\r\n");
            continue;
        }

        if (nCol<0||nCol>=(1<<nLevel))
        {
            printf("<p>Error n..Col! n...Col must between 0~%d. </p>\r\n",
            int((1<<nLevel)-1));
            continue;
        }

        if (nRow<0||nRow>=(1<<nLevel))
        {
            printf("<p>Error n...Row! n...Row must between 0~%d. </p>\r\n",
            int((1<<nLevel)-1));
            continue;
        }


       if (true==regisit_dbtask(nLevel,nCol,nRow))
        ;

    }
    return 0;
}


具体的思路是如果本地瓦片存在,就读取,不存在,则返回一个固定的二进制图片,告诉他“正在下载”,后台线程会读到写入的瓦片索引内容并下载。

bufempty是存储“正在下载”文字图片的地址。


你可能感兴趣的:(一步步DIY: OSM-Web服务器(八) 使用 C FCGI 返回瓦片并登记下载)