我们有一个 Web 服务 (asmx),它接受字节数组缓冲区并将其流式传输到外部文件服务以进行存储和归档。它由生成相当小的文件 (3-5M) 的 Windows 服务调用,因此创建一个该大小的字节数组并将其作为参数提供给 Web 服务调用直到现在都运行良好。
我的任务是向文件队列添加一个新作业,该作业可能会生成大于 70M 的文件。显然,这样大小的 byte[]
会占用系统内存,所以我一直在寻找解决方案。 Web 服务有一个将 FileStream
作为参数而不是 byte[]
的内部方法,因此我尝试将 FileStream 方法作为 WebMethod 出现。我已经更新了 Windows 服务中的引用,但发生了一件奇怪的事情:FileStream 参数附加了一个命名空间说明符(类似于 CallingWindowsService.ExternalWebServiceFileManager.FileStream
)并且这个指定的对象没有文件名作为构造函数,所以我无法打开特定文件。
我完全不知道如何处理这个问题。有没有其他人这样做过 - 将大量数据流式传输到 网络服务 - 如果是这样,最好的方法是什么?我的 Web 服务将需要 byte[]
或 FileStream
。
查看其他一些消息,看起来 MTOM(不熟悉它)可能是一个解决方案,但我不确定如何在我的网络方法中设置它或让它工作。
最佳答案
您可以尝试一些事情,您没有提及您使用的是什么协议(protocol)或您如何托管它,所以我假设它可能是 IIS7 和您使用的 soap。在 Web 服务的 web.config 文件中,您可以添加以下内容,这将增加允许传输的文件大小而不会出现 404 错误:
<system.web>
<httpRuntime executionTimeout="999999" maxRequestLength="2097151" />
...
</system.web>
您可能想对 Web 服务的 web.config 文件做的第二件事是允许大文件传输:
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2000000000" />
</requestFiltering>
</security>
</system.webServer>
另一种可能性:
<location path="Copy.asmx"> <!-- Name of you asmx -->
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="104857600"/> <!-- 100 megs -->
</requestFiltering>
</security>
</system.webServer>
</location>
通过 Web 服务发送 byte[] 的主要问题是它们被放入 SOAP 体中,SOAP 体被编码为 base 64 字符串。像这样对文件进行编码会使 soap 主体中的文件大小增加多达三分之二(即,一个 6 MB 的文件通过网络变成一个 9 MB 的文件)。
另一种可能性是“分块”,在传输之前将您的数据分成更小的段,这可能是您所需要的。根据网络速度、服务器资源等因素,chunkSize(设置为 500KB)可能是提高上传性能的关键因素。
/// <summary>
/// Chunk the file and upload
/// </summary>
/// <param name="filename"></param>
private void UploadVideo(string filename)
{
#region Vars
const int chunkSize = 512000;
byte[] bytes = null;
int startIndex, endIndex, length, totalChunks;
WS.UploadRequest objRequest = new WS.UploadRequest();
#endregion
try
{
if (File.Exists(filename))
{
using (WS.UploadService objService = new WS.UploadService())
{
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
{
//// Calculate total chunks to be sent to service
totalChunks = (int)Math.Ceiling((double)fs.Length / chunkSize);
//// Set up Upload request object
objRequest.FileName = filename;
objRequest.FileSize = fs.Length;
for (int i = 0; i < totalChunks; i++)
{
startIndex = i * chunkSize;
endIndex = (int)(startIndex + chunkSize > fs.Length ? fs.Length : startIndex + chunkSize);
length = endIndex - startIndex;
bytes = new byte[length];
//// Read bytes from file, and send upload request
fs.Read(bytes, 0, bytes.Length);
objRequest.FileBytes = bytes;
objService.UploadVideo(objRequest);
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(string.Format("Error- {0}", ex.Message));
}
关于c# - 将大文件流式传输到 Web 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10115011/