6

我们有一个 Web 服务 (asmx),它采用字节数组缓冲区并将其流式传输到外部文件服务以进行存储和归档。它由生成相当小文件 (3-5M) 的 Windows 服务调用,因此创建一个字节数组大小并将其作为参数提供给 Web 服务调用到目前为止运行良好。

我的任务是向文件队列中添加一个新作业,该作业可能会生成大于 70M 的文件。显然byte[],这样的大小会压倒系统内存,所以我一直在寻找解决方案。Web 服务有一个将 aFileStream作为参数而不是 a的内部方法byte[],因此我尝试将 FileStream 方法显示为 WebMethod。我已经更新了 Windows 服务中的引用,但是发生了一件奇怪的事情:FileStream 参数附加了一个命名空间说明符(类似于CallingWindowsService.ExternalWebServiceFileManager.FileStream),并且这个指定的对象没有文件名作为构造函数,所以我无法打开特定文件.

我完全不知道如何处理这个问题。有没有其他人这样做过 - 将大量数据流式传输Web 服务 - 如果是这样,最好的方法是什么?我的网络服务将需要 abyte[]FileStream.

查看其他一些消息,看起来 MTOM(不熟悉它)可能是一个解决方案,但我不确定如何在我的 Web 方法中设置它或让它工作。

4

3 回答 3

3

您可以尝试一些事情,您没有提及您使用的协议或托管它的方式,所以我假设它可能是 IIS7 和您使用的肥皂。在 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 主体中,该主体被编码为 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));
    }
于 2012-04-12T01:47:00.473 回答
1

ASMXWeb 服务是不应该用于新开发的遗留技术。

它缺少的功能之一是支持流式传输和大文件。特别是,一条消息在发送到客户端的途中将在内存中最多重复四次。

WCF确实支持真正的流媒体。

于 2012-04-11T23:17:37.300 回答
-1

正如@John Saunders 所说,Web 服务对流和大文件大小处理的支持很差,您可以使用压缩通过 Web 服务传输文件,而不是发送原始文件。

于 2012-04-12T01:19:59.550 回答