我在IIS Web服务器上设置了一个简单的php服务。我的客户端使用它从服务器检索文件。它看起来像这样:
<?php
if (isset($_GET['file']))
{
$filepath = "C:\\files\\" . $_GET['file'];
if (!strpos(pathinfo($filepath, PATHINFO_DIRNAME), "..") && file_exists($filepath) && !is_dir($filepath))
{
set_time_limit(0);
$fp = @fopen($filepath, "rb");
while(!feof($fp))
{
print(@fread($fp, 1024*8));
ob_flush();
flush();
}
}
else
{
echo "ERROR at www.testserver.com\r\n";
}
exit;
}
?>
我在C ++中使用WinHttp的WinHttpReadData检索文件。
编辑#2:这是C ++代码。这不完全是我的程序中出现的方式。我不得不从多个班级中提取作品,但要点应该是显而易见的。
session = WinHttpOpen(appName.c_str(), WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
if (session) connection = WinHttpConnect(session, hostName.c_str(), INTERNET_DEFAULT_HTTP_PORT, 0);
if (connection) request = WinHttpOpenRequest(connection, NULL, requestString.c_str(), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
bool results = false;
if (request)
{
results = (WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0) != FALSE);
}
if (results)
{
results = (WinHttpReceiveResponse(request, NULL) != FALSE);
}
DWORD bytesCopied = 0;
DWORD size = 0;
if (results)
{
do {
results = (WinHttpQueryDataAvailable(request, &size) != FALSE);
if (results)
{
// More available data?
if (size > 0)
{
// Read the Data.
size = min(bufferSize, size);
ZeroMemory(buffer, size);
results = (WinHttpReadData(request, (LPVOID)buffer, size, &bytesCopied) != FALSE);
}
}
if (bytesCopied > 0 && !SharedShutDown.GetValue())
{
tempFile.write((PCHAR)RequestBuffer, bytesCopied);
if (tempFile.fail())
{
tempFile.close();
return false;
}
fileBytes += bytesCopied;
}
} while (bytesCopied > 0 && !SharedShutDown.GetValue());
}
当我使用Windows 7或Windows 10计算机上的服务器计算机名称在本地网络上测试(数千个文件)时,一切正常。当我从Windows 7计算机通过Internet访问服务时,它也可以正常工作。但是,当我在通过互联网访问的Windows 10计算机上运行客户端时,我会删除字符。有趣的是,它是每次从XML文件中删除的特定字符集。 (其他,二进制,文件也会受到影响,但我还没有确定它们有什么变化。)
如果XML文件包含以“<Style
”开头的元素,则该文本将消失。所以,这个:
<Element1>blah blah</Element1>
<Style_Element>hoopa hoopa</Style_Element>
<Element2>bip bop bam</Element2>
成为这个:
<Element1>blah blah</Element1>
_Element>hoopa hoopa</Style_Element>
<Element2>bip bop bam</Element2>
请注意,样式元素的开头被切掉了。这是唯一受影响的元素,如果文件中有多个元素,它似乎只影响第一个元素。
令我困惑的是为什么从Windows 7运行客户端不会发生这种情况。
编辑:其他一些文件(二进制和文本)每个缺少1到3个字符。似乎只在文件中发生一次丢弃。文件的其余内容与源代码相同。
答案 0 :(得分:0)
我无法理解上述阅读程序,它也是不完整的。请保持简单,如下例所示。
您遇到二进制文件问题时,建议您不要以二进制模式打开输出tempFile
。
std::ofstream tempFile(filename, std::ios::binary);
while(WinHttpQueryDataAvailable(request, &size) && size)
{
std::string buf(size, 0);
WinHttpReadData(request, &buf[0], size, &bytesCopied);
tempFile.write(buf.data(), bytesCopied);
}
您的php文件可以简化如下:
<?php
readfile('whatever.bin');
?>
答案 1 :(得分:0)
我似乎解决了这个问题。我的php服务没有包含头信息(我认为我不需要它),所以我想我会尝试为内容类型application / octet-stream添加一个头规范,看看会产生什么结果。我的更新服务看起来像这样:
if (isset($_GET['file']))
{
$filepath = "C:\\Program Files (Unrestricted)\\Sony Online Entertainment\\Everquest Yarko Client\\" . $_GET['file'];
if (!strpos(pathinfo($filepath, PATHINFO_DIRNAME), "..") && file_exists($filepath) && !is_dir($filepath))
{
header("Content-Type:application/octet-stream");
set_time_limit(0);
$fp = @fopen($filepath, "rb");
while(!feof($fp))
{
print(@fread($fp, 1024*8));
ob_flush();
flush();
}
}
else
{
echo "ERROR at www.lewiefitz.com\r\n";
}
exit;
}
现在,文件下载没有任何损坏。为什么我在这种情况下需要这样的标题是超出我的。系统的哪个部分在响应消息最终进入缓冲区之前搞乱了?我不知道。