如何在不保存文件的情况下制作打印屏幕并将其发送到 FTP 服务器?我的工作代码将文件保存到硬盘
Posted
技术标签:
【中文标题】如何在不保存文件的情况下制作打印屏幕并将其发送到 FTP 服务器?我的工作代码将文件保存到硬盘【英文标题】:How to make and send a print screen to a FTP server without save the file? My working code save the files to HDD 【发布时间】:2017-01-13 22:53:34 【问题描述】:在发表这篇文章之前,我搜索并尝试了 4 天,例如 https://www.codeproject.com/kb/gdi-plus/memimage.aspx,但我是编程新手。
这段代码(不是我的),制作了一个打印屏幕,保存到一个文件,然后被发送到一个 ftp 服务器。我想这样做而不将文件保存到硬盘,从内存到 FTP。
// The print-screen and save to file (jpg) code:
wstring wtmp;
tmp = sDate + pictureName + ".jpeg";
wtmp = ToStringW(tmp);
screenName = wtmp.c_str();
ftpScreenName = wtmp.c_str();
fileToRemove = tmp.c_str();
using namespace Gdiplus;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
HDC scrdc, memdc;
HBITMAP membit;
scrdc = ::GetDC(0);
int Height = GetSystemMetrics(SM_CYSCREEN);
int Width = GetSystemMetrics(SM_CXSCREEN);
memdc = CreateCompatibleDC(scrdc);
membit = CreateCompatibleBitmap(scrdc, Width, Height);
HBITMAP hOldBitmap = (HBITMAP)SelectObject(memdc, membit);
BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);
Gdiplus::Bitmap bitmap(membit, NULL);
EncoderParameters encoderParameters;
ULONG quality;
CLSID clsid;
GetEncoderClsid(L"image/jpeg", &clsid);
encoderParameters.Count = 1;
encoderParameters.Parameter[0].Guid = EncoderQuality;
encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
encoderParameters.Parameter[0].NumberOfValues = 1;
// Save the image as a JPEG with quality level 80.
quality = 80;
encoderParameters.Parameter[0].Value = &quality;
int result;
result = bitmap.Save(screenName, &clsid); //saving the file to HDD
//send to ftp with given info
saveFTP(server, user, password, ftpScreenName, screenName);
GdiplusShutdown(gdiplusToken);
//这里是FTP客户端部分:
bool saveFTP(LPCWSTR l_server, LPCWSTR l_user, LPCWSTR l_pass, LPCWSTR l_ftpfile, LPCWSTR l_screen)
HINTERNET internet = InternetOpen(L"tester", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_ASYNC);
HINTERNET inter = InternetConnect(internet, l_server, INTERNET_DEFAULT_FTP_PORT, l_user, l_pass, INTERNET_SERVICE_FTP, 0, 0);
bool result;
result = FtpPutFile(inter, l_screen, l_ftpfile, FTP_TRANSFER_TYPE_BINARY, 0);
InternetCloseHandle(inter);
InternetCloseHandle(internet);
return result;
【问题讨论】:
【参考方案1】:使用FtpOpenFile()
和InternetWriteFile()
代替FtpPutFile()
。这在FtpPutFile()
文档中有明确说明:
FtpPutFile
是一个高级例程,它处理与在本地读取文件并将其存储在 FTP 服务器上相关的所有簿记和开销。 只需要发送文件数据或需要密切控制文件传输的应用程序应使用FtpOpenFile
和InternetWriteFile
函数。
以及在 WinInet 的 FTP Sessions 文档中
要在 FTP 服务器上上传或放置文件,应用程序可以使用
FtpPutFile
或FtpOpenFile
(以及InternetWriteFile
)。FtpPutFile
可以用于本地已经存在的文件,而FtpOpenFile
和InternetWriteFile
可以用于将数据写入 FTP 服务器上的文件。
Gdiplus::Bitmap
可以保存到 HDD 文件或IStream
。您可以使用
使用CreateStreamOnHGlobal()
或SHCreateMemStream()
创建内存流,然后将Bitmap
保存到流中,最后使用FtpOpenFile()
和InternetWriteFile()
上传流的内容。
例如(为简洁起见省略了错误处理,不要在实际代码中省略它!):
tmp = sDate + pictureName + ".jpeg";
wstring wtmp = ToStringW(tmp);
IStream *strm = SHCreateMemStream(NULL, 0);
using namespace Gdiplus;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
CLSID clsid;
GetEncoderClsid(L"image/jpeg", &clsid);
EncoderParameters encoderParameters;
encoderParameters.Count = 1;
encoderParameters.Parameter[0].Guid = EncoderQuality;
encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
encoderParameters.Parameter[0].NumberOfValues = 1;
// Save the image as a JPEG with quality level 80.
ULONG quality = 80;
encoderParameters.Parameter[0].Value = &quality;
HDC scrdc = ::GetDC(0);
int Height = GetSystemMetrics(SM_CYSCREEN);
int Width = GetSystemMetrics(SM_CXSCREEN);
HDC memdc = CreateCompatibleDC(scrdc);
HBITMAP membit = CreateCompatibleBitmap(scrdc, Width, Height);
HBITMAP hOldBitmap = (HBITMAP) SelectObject(memdc, membit);
BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);
Gdiplus::Bitmap bitmap(membit, NULL);
bitmap.Save(strm, &clsid); //saving the file to HDD
SelectObject(memdc, hOldBitmap);
DeleteObject(membit);
DeleteDC(memdc);
::ReleaseDC(0, scrdc);
GdiplusShutdown(gdiplusToken);
LARGE_INTEGER li;
li.QuadPart = 0;
strm->Seek(li, STREAM_SEEK_SET, NULL);
//send to ftp with given info
saveFTP(server, user, password, wtmp.c_str(), strm);
strm->Release();
bool saveFTP(LPCWSTR l_server, LPCWSTR l_user, LPCWSTR l_pass, LPCWSTR l_ftpfile, IStream *l_screen)
HINTERNET internet = InternetOpen(L"tester", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_ASYNC);
HINTERNET conn = InternetConnect(internet, l_server, INTERNET_DEFAULT_FTP_PORT, l_user, l_pass, INTERNET_SERVICE_FTP, 0, 0);
HINTERNET file = FtpOpenFile(conn, l_ftpfile, GENERIC_WRITE, FTP_TRANSFER_TYPE_BINARY, 0);
BYTE buffer[1024], *pbuf;
ULONG ulRead;
DWORD dwWritten;
HRESULT hr;
bool success = true;
do
hr = l_screen->Read(buffer, sizeof(buffer), &ulRead);
if (FAILED(hr))
success = false;
break;
pbuf = buffer;
while (ulRead != 0)
if (!InternetWriteFile(file, pbuf, ulRead, &dwWritten))
success = false;
break;
pbuf += dwWritten;
ulRead -= dwWritten;
while (hr == S_OK);
InternetCloseHandle(file);
InternetCloseHandle(conn);
InternetCloseHandle(internet);
return success;
【讨论】:
感谢雷米的回复。现在我必须替换 result = FtpPutFile(inter, l_screen, l_ftpfile, FTP_TRANSFER_TYPE_BINARY, 0); InternetCloseHandle(inter);互联网关闭句柄(互联网);结果 = FtpOpenFile()(inter, l_screen, l_ftpfile, FTP_TRANSFER_TYPE_BINARY, 0); InternetWriteFile(inter); InternetCloseHandle(inter); InternetCloseHandle(internet); 你能告诉我我必须在我的代码中写哪些参数: InternetWriteFile( __in HINTERNET hFile, __in_bcount(dwNumberOfBytesToWrite) LPCVOID lpBuffer, __in DWORD dwNumberOfBytesToWrite, __out LPDWORD lpdwNumberOfBytesWritten ); 谢谢先生!我在代码的第一部分只有一个错误:SHCreateMemStream undefined。 @snowman 如果你阅读了我链接的文档,你需要在你的代码中使用#include <Shlwapi.h>
并链接到Shlwapi.lib
。
对不起,我是新手。我通过添加 #include 以上是关于如何在不保存文件的情况下制作打印屏幕并将其发送到 FTP 服务器?我的工作代码将文件保存到硬盘的主要内容,如果未能解决你的问题,请参考以下文章
如何在不将 csv 保存到磁盘的情况下将 csv 格式的数据从内存发送到数据库?
如何在不使用 Ruby 保存到磁盘的情况下生成 zip 文件?