基于socket实现http上传
This commit is contained in:
parent
e94c452962
commit
9d13c4228a
|
@ -1557,10 +1557,185 @@ bool Manager::SaveBase64(const std::string& fileName, const char* base64)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static std::string MakePreFileData(const char* pszBoundary, const char* pszRemoteFileName)
|
||||
{
|
||||
char data[512];
|
||||
sprintf(data, "--%s\r\nContent-Disposition: form-data; name=\"filedata\"; filename=\"%s\"\r\n",
|
||||
pszBoundary, pszRemoteFileName);
|
||||
std::string ret = data;
|
||||
ret += "Content-Type: application/octet-stream; charset=utf-8\r\n";
|
||||
ret += "Content-Transfer-Encoding: binary\r\n";
|
||||
ret += "\r\n";
|
||||
return ret;
|
||||
}
|
||||
|
||||
static std::string MakePostFileData(const char* pszBoundary)
|
||||
{
|
||||
char data[512];
|
||||
sprintf(data, "\r\n--%s\r\nContent-Disposition: form-data; name=\"submitted\"\r\n\r\nsubmit\r\n--%s--\r\n", pszBoundary, pszBoundary);
|
||||
return data;
|
||||
}
|
||||
|
||||
static void ParseHttpURL(const std::string &url, std::string &addr, int &port, std::string &path)
|
||||
{
|
||||
addr.clear();
|
||||
port = 0;
|
||||
path.clear();
|
||||
|
||||
std::string url2;
|
||||
std::string::size_type pos = url.find("//");
|
||||
if (std::string::npos != pos)
|
||||
{
|
||||
std::string protocal = url.substr(0, pos);
|
||||
if (protocal != "http:")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
url2 = url.substr(pos + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
url2 = url;
|
||||
}
|
||||
|
||||
std::string addr_port;
|
||||
pos = url2.find("/");
|
||||
if (std::string::npos != pos)
|
||||
{
|
||||
addr_port = url2.substr(0, pos);
|
||||
path = url2.substr(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
addr_port = url2;
|
||||
}
|
||||
|
||||
pos = addr_port.find(":");
|
||||
if (std::string::npos != pos)
|
||||
{
|
||||
addr = addr_port.substr(0, pos);
|
||||
port = atoi(addr_port.substr(pos + 1).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = addr_port;
|
||||
port = 80;
|
||||
}
|
||||
}
|
||||
|
||||
bool Manager::HTTPUpload(const std::string& localFileName, const std::string& httpUrl, const std::string& remoteFileName,
|
||||
const std::string& httpMethod, const std::string& header, const std::string& param)
|
||||
{
|
||||
return false;
|
||||
unsigned char* fileData = NULL;
|
||||
long fileSize = 0;
|
||||
FILE* file = fopen(localFileName.c_str(), "rb");
|
||||
if (NULL != file)
|
||||
{
|
||||
fseek(file, 0, SEEK_END);
|
||||
fileSize = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
if (0 != fileSize)
|
||||
{
|
||||
fileData = new unsigned char[fileSize];
|
||||
fread(fileData, 1, fileSize, file);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
if (NULL == fileData)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string addr;
|
||||
int port;
|
||||
std::string path;
|
||||
ParseHttpURL(httpUrl, addr, port, path);
|
||||
|
||||
SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
|
||||
assert(INVALID_SOCKET != sockClient);
|
||||
|
||||
u_long ul = 1; // 设为非阻塞
|
||||
ioctlsocket(sockClient, FIONBIO, &ul);
|
||||
|
||||
SOCKADDR_IN addrServer = { 0 };
|
||||
addrServer.sin_addr.S_un.S_addr = inet_addr(addr.c_str());
|
||||
addrServer.sin_family = AF_INET;
|
||||
addrServer.sin_port = htons(port);
|
||||
if (0 != connect(sockClient, (SOCKADDR*)&addrServer, sizeof(SOCKADDR_IN)))
|
||||
{
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(sockClient, &fds);
|
||||
timeval tm;
|
||||
tm.tv_sec = 1;
|
||||
tm.tv_usec = 0;
|
||||
|
||||
if (select((int)(sockClient + 1), NULL, &fds, NULL, &tm) <= 0)
|
||||
{
|
||||
closesocket(sockClient);
|
||||
delete[] fileData;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!FD_ISSET(sockClient, &fds))
|
||||
{
|
||||
closesocket(sockClient);
|
||||
delete[] fileData;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ul = 0; // 设为阻塞
|
||||
ioctlsocket(sockClient, FIONBIO, &ul);
|
||||
|
||||
char remoteName[256];
|
||||
HGBase_GetFileName(localFileName.c_str(), remoteName, 256);
|
||||
|
||||
bool ret = false;
|
||||
|
||||
const char* pszBoundary = "---------------------------7d33a816d302b6";
|
||||
|
||||
std::string strPreFileData = MakePreFileData(pszBoundary, remoteName);
|
||||
std::string strPostFileData = MakePostFileData(pszBoundary);
|
||||
|
||||
char hostname[128];
|
||||
gethostname(hostname, 128);
|
||||
|
||||
std::string head;
|
||||
char data[512];
|
||||
sprintf(data, "POST %s HTTP/1.1\r\nHost: %s\r\n", path.c_str(), hostname);
|
||||
head += data;
|
||||
sprintf(data, "Content-Type: multipart/form-data; boundary=%s\r\n", pszBoundary);
|
||||
head += data;
|
||||
sprintf(data, "Content-Length: %d\r\n\r\n", strPreFileData.size() + fileSize + strPostFileData.size());
|
||||
head += data;
|
||||
|
||||
send(sockClient, head.c_str(), head.size(), 0);
|
||||
send(sockClient, strPreFileData.c_str(), strPreFileData.size(), 0);
|
||||
send(sockClient, (const char *)fileData, fileSize, 0);
|
||||
send(sockClient, strPostFileData.c_str(), strPostFileData.size(), 0);
|
||||
|
||||
char recvBuf[2048] = {0};
|
||||
recv(sockClient, recvBuf, 2048, 0);
|
||||
|
||||
std::string strRecv(recvBuf);
|
||||
std::string::size_type pos = strRecv.find("\r\n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
std::string head = strRecv.substr(0, pos);
|
||||
if (head.find("200") != std::string::npos)
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
closesocket(sockClient);
|
||||
delete[] fileData;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static size_t read_callback(char* ptr, size_t size, size_t nmemb, void* stream)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,249 @@
|
|||
/* The CGI_C library, by Thomas Boutell, version 2.01. CGI_C is intended
|
||||
to be a high-quality API to simplify CGI programming tasks. */
|
||||
|
||||
/* Make sure this is only included once. */
|
||||
|
||||
#ifndef CGI_C
|
||||
#define CGI_C 1
|
||||
|
||||
/* Ensure proper linkage to c++ programs. */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Bring in standard I/O since some of the functions refer to
|
||||
types defined by it, such as FILE *. */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* The various CGI environment variables. Instead of using getenv(),
|
||||
the programmer should refer to these, which are always
|
||||
valid null-terminated strings (they may be empty, but they
|
||||
will never be null). If these variables are used instead
|
||||
of calling getenv(), then it will be possible to save
|
||||
and restore CGI environments, which is highly convenient
|
||||
for debugging. */
|
||||
|
||||
extern char *cgiServerSoftware;
|
||||
extern char *cgiServerName;
|
||||
extern char *cgiGatewayInterface;
|
||||
extern char *cgiServerProtocol;
|
||||
extern char *cgiServerPort;
|
||||
extern char *cgiRequestMethod;
|
||||
extern char *cgiPathInfo;
|
||||
extern char *cgiPathTranslated;
|
||||
extern char *cgiScriptName;
|
||||
extern char *cgiQueryString;
|
||||
extern char *cgiRemoteHost;
|
||||
extern char *cgiRemoteAddr;
|
||||
extern char *cgiAuthType;
|
||||
extern char *cgiRemoteUser;
|
||||
extern char *cgiRemoteIdent;
|
||||
extern char *cgiContentType;
|
||||
extern char *cgiAccept;
|
||||
extern char *cgiUserAgent;
|
||||
extern char *cgiReferrer;
|
||||
|
||||
/* Cookies as sent to the server. You can also get them
|
||||
individually, or as a string array; see the documentation. */
|
||||
extern char *cgiCookie;
|
||||
|
||||
/* A macro providing the same incorrect spelling that is
|
||||
found in the HTTP/CGI specifications */
|
||||
#define cgiReferer cgiReferrer
|
||||
|
||||
/* The number of bytes of data received.
|
||||
Note that if the submission is a form submission
|
||||
the library will read and parse all the information
|
||||
directly from cgiIn; the programmer need not do so. */
|
||||
|
||||
extern int cgiContentLength;
|
||||
|
||||
/* Pointer to CGI output. The cgiHeader functions should be used
|
||||
first to output the mime headers; the output HTML
|
||||
page, GIF image or other web document should then be written
|
||||
to cgiOut by the programmer. In the standard CGIC library,
|
||||
cgiOut is always equivalent to stdout. */
|
||||
|
||||
extern FILE *cgiOut;
|
||||
|
||||
/* Pointer to CGI input. The programmer does not read from this.
|
||||
We have continued to export it for backwards compatibility
|
||||
so that cgic 1.x applications link properly. */
|
||||
|
||||
extern FILE *cgiIn;
|
||||
|
||||
/* Possible return codes from the cgiForm family of functions (see below). */
|
||||
|
||||
typedef enum {
|
||||
cgiFormSuccess,
|
||||
cgiFormTruncated,
|
||||
cgiFormBadType,
|
||||
cgiFormEmpty,
|
||||
cgiFormNotFound,
|
||||
cgiFormConstrained,
|
||||
cgiFormNoSuchChoice,
|
||||
cgiFormMemory,
|
||||
cgiFormNoFileName,
|
||||
cgiFormNoContentType,
|
||||
cgiFormNotAFile,
|
||||
cgiFormOpenFailed,
|
||||
cgiFormIO,
|
||||
cgiFormEOF
|
||||
} cgiFormResultType;
|
||||
|
||||
/* These functions are used to retrieve form data. See
|
||||
cgic.html for documentation. */
|
||||
|
||||
extern cgiFormResultType cgiFormString(
|
||||
char *name, char *result, int max);
|
||||
|
||||
extern cgiFormResultType cgiFormStringNoNewlines(
|
||||
char *name, char *result, int max);
|
||||
|
||||
|
||||
extern cgiFormResultType cgiFormStringSpaceNeeded(
|
||||
char *name, int *length);
|
||||
|
||||
|
||||
extern cgiFormResultType cgiFormStringMultiple(
|
||||
char *name, char ***ptrToStringArray);
|
||||
|
||||
extern void cgiStringArrayFree(char **stringArray);
|
||||
|
||||
extern cgiFormResultType cgiFormInteger(
|
||||
char *name, int *result, int defaultV);
|
||||
|
||||
extern cgiFormResultType cgiFormIntegerBounded(
|
||||
char *name, int *result, int min, int max, int defaultV);
|
||||
|
||||
extern cgiFormResultType cgiFormDouble(
|
||||
char *name, double *result, double defaultV);
|
||||
|
||||
extern cgiFormResultType cgiFormDoubleBounded(
|
||||
char *name, double *result, double min, double max, double defaultV);
|
||||
|
||||
extern cgiFormResultType cgiFormSelectSingle(
|
||||
char *name, char **choicesText, int choicesTotal,
|
||||
int *result, int defaultV);
|
||||
|
||||
|
||||
extern cgiFormResultType cgiFormSelectMultiple(
|
||||
char *name, char **choicesText, int choicesTotal,
|
||||
int *result, int *invalid);
|
||||
|
||||
/* Just an alias; users have asked for this */
|
||||
#define cgiFormSubmitClicked cgiFormCheckboxSingle
|
||||
|
||||
extern cgiFormResultType cgiFormCheckboxSingle(
|
||||
char *name);
|
||||
|
||||
extern cgiFormResultType cgiFormCheckboxMultiple(
|
||||
char *name, char **valuesText, int valuesTotal,
|
||||
int *result, int *invalid);
|
||||
|
||||
extern cgiFormResultType cgiFormRadio(
|
||||
char *name, char **valuesText, int valuesTotal,
|
||||
int *result, int defaultV);
|
||||
|
||||
/* The paths returned by this function are the original names of files
|
||||
as reported by the uploading web browser and shoult NOT be
|
||||
blindly assumed to be "safe" names for server-side use! */
|
||||
extern cgiFormResultType cgiFormFileName(
|
||||
char *name, char *result, int max);
|
||||
|
||||
/* The content type of the uploaded file, as reported by the browser.
|
||||
It should NOT be assumed that browsers will never falsify
|
||||
such information. */
|
||||
extern cgiFormResultType cgiFormFileContentType(
|
||||
char *name, char *result, int max);
|
||||
|
||||
extern cgiFormResultType cgiFormFileSize(
|
||||
char *name, int *sizeP);
|
||||
|
||||
typedef struct cgiFileStruct *cgiFilePtr;
|
||||
|
||||
extern cgiFormResultType cgiFormFileOpen(
|
||||
char *name, cgiFilePtr *cfpp);
|
||||
|
||||
extern cgiFormResultType cgiFormFileRead(
|
||||
cgiFilePtr cfp, char *buffer, int bufferSize, int *gotP);
|
||||
|
||||
extern cgiFormResultType cgiFormFileClose(
|
||||
cgiFilePtr cfp);
|
||||
|
||||
extern cgiFormResultType cgiCookieString(
|
||||
char *name, char *result, int max);
|
||||
|
||||
extern cgiFormResultType cgiCookieInteger(
|
||||
char *name, int *result, int defaultV);
|
||||
|
||||
cgiFormResultType cgiCookies(
|
||||
char ***ptrToStringArray);
|
||||
|
||||
typedef enum {
|
||||
cgiCookieSecure = 1,
|
||||
cgiCookieHttpOnly = 2,
|
||||
cgiCookieSameSiteStrict = 4
|
||||
} cgiCookieOption;
|
||||
|
||||
/* path can be null or empty in which case a path of / (entire site) is set.
|
||||
domain can be a single web site; if it is an entire domain, such as
|
||||
'boutell.dev', it should begin with a dot: '.boutell.dev' */
|
||||
extern void cgiHeaderCookieSet(char *name, char *value,
|
||||
int secondsToLive, char *path, char *domain, int options);
|
||||
extern void cgiHeaderCookieSetString(char *name, char *value,
|
||||
int secondsToLive, char *path, char *domain);
|
||||
extern void cgiHeaderCookieSetInteger(char *name, int value,
|
||||
int secondsToLive, char *path, char *domain);
|
||||
extern void cgiHeaderLocation(char *redirectUrl);
|
||||
extern void cgiHeaderStatus(int status, char *statusMessage);
|
||||
extern void cgiHeaderContentType(char *mimeType);
|
||||
|
||||
typedef enum {
|
||||
cgiEnvironmentIO,
|
||||
cgiEnvironmentMemory,
|
||||
cgiEnvironmentSuccess,
|
||||
cgiEnvironmentWrongVersion
|
||||
} cgiEnvironmentResultType;
|
||||
|
||||
extern cgiEnvironmentResultType cgiWriteEnvironment(char *filename);
|
||||
extern cgiEnvironmentResultType cgiReadEnvironment(char *filename);
|
||||
|
||||
extern int cgiMain();
|
||||
|
||||
extern cgiFormResultType cgiFormEntries(
|
||||
char ***ptrToStringArray);
|
||||
|
||||
/* Output string with the <, &, and > characters HTML-escaped.
|
||||
's' is null-terminated. Returns cgiFormIO in the event
|
||||
of error, cgiFormSuccess otherwise. */
|
||||
cgiFormResultType cgiHtmlEscape(const char *s);
|
||||
|
||||
/* Output data with the <, &, and > characters HTML-escaped.
|
||||
'data' is not null-terminated; 'len' is the number of
|
||||
bytes in 'data'. Returns cgiFormIO in the event
|
||||
of error, cgiFormSuccess otherwise. */
|
||||
cgiFormResultType cgiHtmlEscapeData(const char *data, int len);
|
||||
|
||||
/* Output string with the " character HTML-escaped, and no
|
||||
other characters escaped. This is useful when outputting
|
||||
the contents of a tag attribute such as 'href' or 'src'.
|
||||
's' is null-terminated. Returns cgiFormIO in the event
|
||||
of error, cgiFormSuccess otherwise. */
|
||||
cgiFormResultType cgiValueEscape(const char *s);
|
||||
|
||||
/* Output data with the " character HTML-escaped, and no
|
||||
other characters escaped. This is useful when outputting
|
||||
the contents of a tag attribute such as 'href' or 'src'.
|
||||
'data' is not null-terminated; 'len' is the number of
|
||||
bytes in 'data'. Returns cgiFormIO in the event
|
||||
of error, cgiFormSuccess otherwise. */
|
||||
cgiFormResultType cgiValueEscapeData(const char *data, int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* CGI_C */
|
||||
|
Loading…
Reference in New Issue