vc++ socket http协议post方法上传(分块上传)

最近项目需要,通过C++客户端向Web服务器用http协议上传文件,网上介绍这方面的好像很少,所以做了个基础的发上来供学习交流;

本人学c++没几天,代码可能比较烂,大家凑合看吧。。

示例代码:

1、C++ Clinet

#include "stdio.h"
#include "WinSock2.h"
#include "iostream"
using namespace std;
#pragma comment(lib,"ws2_32.lib")
long l_file_len;
//获取文件内容
bool file_con(char **buffer,LPCSTR file)   
{   
  FILE *fp = fopen(file, "rb"); 
  if(fp==NULL)
  {
	  printf("文件上传失败,请检查文件路径.....\n");
	  return false;
  }
  fseek(fp, 0, SEEK_END);   
  l_file_len = ftell(fp);   
  rewind(fp);   
    
  *buffer = new char[l_file_len + 1];   
  memset(*buffer, 0, l_file_len + 1);    
  fseek(fp, 0, SEEK_SET);
  fread(*buffer, sizeof(char), l_file_len, fp);
  fclose(fp);  
  return true;
}

//文件上传
std::string upload(LPCSTR lpszServer,LPCSTR lpszAddr,LPCSTR fileUrl)   
{   
	char *file = NULL;   
	if(!file_con(&file,fileUrl))
	{
		 return "0";
	}
	SOCKET sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);   
	if (sock == INVALID_SOCKET)   
	return "0";   
	SOCKADDR_IN server;   
	server.sin_family = AF_INET;   
	server.sin_port = htons(80);   
	struct hostent *host_addr = gethostbyname(lpszServer);   
	if (host_addr == NULL)   
	return "host_addr == NULL";   
	server.sin_addr.s_addr = *((int *) *host_addr->h_addr_list);   
	if (::connect(sock, (SOCKADDR *) &server, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)   
	{   
		::closesocket(sock);   
		return "0";   
	}   
	printf("ip address = %s, port = %d\n",inet_ntoa(server.sin_addr), ntohs(server.sin_port));   
    
	std::string header("");   
	std::string content("");   
//----------------------post头开始--------------------------------
	header +="post ";
	header +=lpszAddr;
	header +=" HTTP/1.1\r\n";
	header +="Host: ";
	header +=lpszServer;
	header += "\r\n";
	header += "User-Agent: Mozilla/4.0\r\n";
	header += "Connection: Keep-Alive\r\n";
	header += "Accept: */*\r\n";
	header += "Pragma: no-cache\r\n";
	header += "Content-Type: multipart/form-data; charset=\"gb2312\"; boundary=----------------------------64b23e4066ed\r\n";

	content += "------------------------------64b23e4066ed\r\n";   
	content += "Content-Disposition: form-data; name=\"file\"; filename=\"大论文和实验材料.rar\"\r\n";   
	content += "Content-Type: aapplication/octet-stream\r\n\r\n";   

	//post尾时间戳
	std::string strContent("\r\n------------------------------64b23e4066ed\r\n");
	char temp[64] = {0}; 
	//注意下面这个参数Content-Length,这个参数值是:http请求头长度+请求尾长度+文件总长度
	sprintf(temp, "Content-Length: %d\r\n\r\n", content.length()+l_file_len+strContent.length());   
	header += temp;   
	std::string str_http_request;
	str_http_request.append(header).append(content); 
//----------------------post头结束-----------------------------------
	//发送post头
	send(sock, str_http_request.c_str(), str_http_request.length(), 0); 

    char fBuff[4096];
	int nPacketBufferSize = 4096; // 每个数据包存放文件的buffer大小
	int nStart;//记录post初始位置
	int nSize;//记录剩余文件大小
	// 就分块传送
	for (int i = 0; i < l_file_len; i += nPacketBufferSize)
	{
	    nStart=i;
	    if (i + nPacketBufferSize + 1> l_file_len)
		{
			nSize = l_file_len - i;
		}
	    else
		{
			nSize = nPacketBufferSize;
		}
	   
	    memcpy(fBuff, file + nStart, nSize);
	    ::send(sock, fBuff, nSize, 0);
	    Sleep(0.2);
	}
  
	::send(sock,strContent.c_str(),strContent.length(),0);

	char szBuffer[1024] = {0};   
	while (true)   
	{

		 int nRet = ::recv(sock, szBuffer, sizeof(szBuffer), 0);   
		 if (nRet == 0 || nRet == WSAECONNRESET)   
		 {   
			 printf("Connection Closed.\n");   
			 break;   
		 }   
		 else if (nRet == SOCKET_ERROR)   
		 {   
			 printf("socket error\n");   
			 break;   
		 }   
		 else   
		 {   
			 printf("recv() returned %d bytes\n", nRet);   
			 printf("received: %s\n", szBuffer);   
			 break;   
		 }   
	}   
	::closesocket(sock);   
	delete [] file;   
	return szBuffer;
}
void main() 
{
	WORD wVersionRequested=MAKEWORD(2,2);
	WSADATA wsaData;
	if(WSAStartup(wVersionRequested,&wsaData))
	{
	    cout<<"加载错误"<<endl;
	}
	if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wHighVersion)!=2)
	{
	    cout<<"WinSock's 加载错误"<<endl;
	}
	upload("localhost","/WebApplication1/Default.aspx","F:\\postgresql-8.3.3-2.rar");
}

2、Web Server

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Text;

namespace WebApplication1
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (Request.Files.Count > 0)
            {
                try
                {
                    HttpPostedFile file = Request.Files[0];
                    string filePath = Request.PhysicalApplicationPath + file.FileName;
                    file.SaveAs(filePath);
                    Response.Write("Success\r\n");
                }
                catch
                {
                    Response.Write("Error\r\n");
                }
                Response.End();
            }
        }
    }
}

上面就是简单的代码示例,web需配置iis,相信大家知道怎么做^_^,还有一点就是web程序默认上传文件的限制,默认上传大小为4M,所以需要

在web.config中设置以下参数:

<httpRuntime maxRequestLength="951200" appRequestQueueLimit="60" executionTimeout="60"/>

这里的maxRequestLength即是默认的上传文件大小,单位是KB。


  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值