通过http协议下载MP3的关键就是 整块打包,一块一块向文件里面存储。读取的时候用二进制
/***
szWebAddr: 页面地址(包含host+addr)
szMp3FileName:将要存储文件的名字
szRequest: 请求内容
szHeadEx: http头附加信息(替换其默认的设置)
iReqType: 请求类型(1--Get;2--Post)
iTimeout: 超时时间(秒)
返回: 页面返回数据
**/
int GetDataFromWebByte(char *szWebAddr,char *szMp3FileName , char *szRequest, char *szHeadEx, int iReqType, int iTimeout) { char szHost[128] = "", szAddr[512] = ""; char szWebBuf[4096] = "", szBuf[4096] = ""; char *pRetData = NULL; //返回的数据 char *szHead = NULL; int iPort = 80, iAppSock; int iRet = 0, iLen, k, iChars, iDone; int iContentLen, iChunked = 0; struct sockaddr_in appHostAddr; struct hostent *pHostent = NULL; int iTransferType = 0, iContent = 0; FILE *fp; WSADATA wsa={0}; if(!szWebAddr) return 0; WSAStartup(MAKEWORD(2,2),&wsa); //获取host和addr和port iRet = GetHostandAddr(szWebAddr, szHost, sizeof(szHost), szAddr, sizeof(szAddr), &iPort); if(iRet < 1) return 0; //获取hostent pHostent = gethostbyname(szHost); if(!pHostent) { iRet = WSAGetLastError(); return 0; } //创建socket appHostAddr.sin_family = AF_INET; appHostAddr.sin_port = htons((unsigned short)iPort); appHostAddr.sin_addr.s_addr = ((struct in_addr *)(pHostent->h_addr))->s_addr; iAppSock = socket(AF_INET, SOCK_STREAM, 0); if(iAppSock == -1) { return 0; } //将创建的Socket连接至应用服务器 if(connect(iAppSock, (void *)&appHostAddr, sizeof(appHostAddr)) == -1) { return 0; } //配置httphead szHead = GetHttpHead(szHost, szAddr, szRequest, szHeadEx, iReqType); if(!szHead) return 0; //向应用服务器发送HTTP请求 if(send(iAppSock, szHead, strlen(szHead), 0) == -1){ return 0; } free(szHead); szHead = NULL; //接收应用服务器返回的数据 memset(szWebBuf, 0, sizeof(szWebBuf)); memset(szBuf, 0, sizeof(szBuf)); k = 0; iChars = 0; iDone = 0; //获取http头信息 while(iDone == 0) { iLen = RecvHttpData(iAppSock, szWebBuf, 1, iTimeout); if(iLen < 1) iDone = 1; switch(*szWebBuf) { case ' ': break; case ' ': if(iChars == 0) iDone = 1; iChars = 0; break; default: iChars++; break; } if(k < sizeof(szBuf) - 1) { szBuf[k] = szWebBuf[0]; k++; } else { pRetData = addRevData(pRetData, szBuf); memset(szBuf, 0, sizeof(szBuf)); k = 0; szBuf[k] = szWebBuf[0]; k++; } } pRetData = addRevData(pRetData, szBuf); //获取http内容长度 //判断是否chunked if(strstr(pRetData, "chunked")) iChunked = 1; //为chunk传输 //获取http内容 iContent = 1; do { if (iChunked > 0) { iContentLen = GetChunkedContentLength(iAppSock); } else { iContentLen = GetContentLength(pRetData); } //获取http内容 //清空数据 if(iContent == 1 && pRetData) { free(pRetData); pRetData = NULL; iContent = 2; } if(iContentLen < 1) { closesocket(iAppSock); //close(iAppSock); return 1; } //chunk memset(szWebBuf, 0, sizeof(szWebBuf)); memset(szBuf, 0, sizeof(szBuf)); k = 0; iChars = iContentLen; //*iLenByte = iChars; iDone = 0; fp = fopen(szMp3FileName , "wb+"); while(iDone == 0) { iLen = RecvHttpData(iAppSock, szWebBuf, 1, iTimeout); if(iLen < 1) iDone = 1; iChars--; if(iChars < 1) iDone = 1; if(k < sizeof(szBuf) - 1) { szBuf[k] = szWebBuf[0]; k++; } else { // puts(szBuf); fwrite(szBuf,1,4096,fp); memset(szBuf, 0, sizeof(szBuf)); k = 0; szBuf[k] = szWebBuf[0]; k++; } } fclose(fp); } while (iChunked); //chunk格式才继续找 closesocket(iAppSock); WSACleanup(); return 1; }
块的大小结合实际情况,却大越好,太小的时候,噪音的频率会很高,影响质量,具体消除噪音,以后再改进。