zoukankan      html  css  js  c++  java
  • Silverlight中用WCF实现文件快速上传(一、基本方法)

    在Silverlight中可能通过服务上传文件。通过服务上传文件可以比较方便地实现异步上传、分块上传、进度显示等等功能。因此,“Silverlight + 服务”组合可以实现比较强大类似于C/S模式中的那种上传功能。下面详细说明实现步骤。

        1. 创建Silverlight应用程序。

        这个是基本能力,不会的先找资料学习一下吧。

        假定创建的解决方案为:UploadFiles。默认情况下存在两个项目:UploadFiles和UploadFiles.Web。

        2. 添加WCF服务。

        在UploadFiles.Web项目中添加WCF服务:右键→添加→新建项→选“启用 Silverlight 功能的 WCF 服务”,如果VS是英文的则为“Silverlight-enabled WCF Service”。

        3. WCF服务的代码:

     namespace UploadFiles.Web
    {
        [ServiceContract(Namespace = "")]
        [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
        public class Service1
        {
            [OperationContract]
            public void DoWork()
            {
                // 在此处添加操作实现
                return;
            }

            // 在此处添加更多操作并使用 [OperationContract] 标记它们
            [OperationContract]
            public void ActionUpload(string fileName, byte[] fileData, bool isAppend)
            {
                //文件上传所在目录
                //可以按日期、文件类型或混合建立相应的文件目录,以便使用
                string uploadFolder = System.Web.Hosting.HostingEnvironment.MapPath("~/upload");

                //目录不存在则新建
                if (!System.IO.Directory.Exists(uploadFolder))
                {
                    System.IO.Directory.CreateDirectory(uploadFolder);
                }

                //文件读写模式
                //如果参数为真则表示续传,以追回模式写文件
                System.IO.FileMode fileMode = isAppend ? System.IO.FileMode.Append : System.IO.FileMode.Create;

                //写入文件
                using (System.IO.FileStream fs = new System.IO.FileStream(uploadFolder + @"\" + fileName, fileMode, System.IO.FileAccess.Write))
                {
                    fs.Write(fileData, 0, fileData.Length);
                }
            }
        }
    }

        4. Silverlight中的上传执行代码

        在MainPage.xaml中添加一个执行上传的按钮,后台执行代码如下:

            private void Button_Click(object sender, RoutedEventArgs e)
            {
                //选择本地文件对话框
                OpenFileDialog openFileDialog = new OpenFileDialog();
                openFileDialog.Filter = "(*.*)|*.*";
                //单选
                openFileDialog.Multiselect = false;

                if (openFileDialog.ShowDialog() == true)
                {
                    //所选上传文件信息
                    FileInfo fileInfo = openFileDialog.File;
                    //上传文件信息
                    UploadFileInfo uploadFileInfo = new UploadFileInfo();
                    uploadFileInfo.Name = fileInfo.Name;
                    //文件内容
                    Stream stream = fileInfo.OpenRead();
                    uploadFileInfo.Size = (int)(stream.Length / 1024);
                    uploadFileInfo.Data = new List<byte[]>();

                    //读取指定大小的文件流内容到uploadFile.Data以便上传
                    int len;
                    long rest;
                    while (stream.Position > -1 && stream.Position < stream.Length)
                    {
                        rest = stream.Length - stream.Position;
                        //len = (rest >= 16384) ? 16384 : (int)rest;  //WCF默认配置参数最大只允许16KB
                        len = (rest >= 2097152) ? 2097152 : (int)rest;  //2MB

                        byte[] fileData = new byte[len];
                        stream.Read(fileData, 0, len);
                        uploadFileInfo.Data.Add(fileData);
                    }

                    stream.Close();

                    localService.Service1Client wcfService = new TestUploadFile_WCF.localService.Service1Client();
                    wcfService.ActionUploadCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(wcfService_ActionUploadCompleted);
                    wcfService.ActionUploadAsync(uploadFileInfo.Name, uploadFileInfo.Data[0], false, uploadFileInfo);
                }

            }

            void wcfService_ActionUploadCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
            {
                if (e.Error == null)
                {
                    UploadFileInfo uploadFileInfo = e.UserState as UploadFileInfo;
                    uploadFileInfo.Status += uploadFileInfo.Data[0].Length / 1024;
                    uploadFileInfo.Data.RemoveAt(0);
                    if (uploadFileInfo.Data.Count == 0)
                    {
                        btnUploadFile.Content = "Uploaded";
                        MessageBox.Show("文件上传成功。");
                    }
                    else
                    {
                        (sender as localService.Service1Client).ActionUploadAsync(uploadFileInfo.Name, uploadFileInfo.Data[0], true, uploadFileInfo);
                        btnUploadFile.Content = uploadFileInfo.Status.ToString() + "/" + uploadFileInfo.Size.ToString() + "KB Uploaded.";
                    }
                }
            }

        辅助类:

        public class UploadFileInfo
        {
            //文件名
            public string Name { get; set; }
            //文件大小
            public int Size { get; set; }
            //上传状态
            public int Status { get; set; }
            //文件流
            public List<byte[]> Data { get; set; }
        }

        5. 上传数据尺寸配置

        默认情况下,WCF只允许最大16KB的数据块上传。按此尺寸,实测上传速度很慢。如果要修改尺寸,则要修改Web.config文件。

        注意:是修改UploadFiles.Web中的Web.config,而不是UploadFiles中的ServiceReferences.ClientConfig。最开始我曾以为是修改后者,结果被困了好久,汗颜!

        网上有好多文章讲修改参数的,但无一指明是修改.Web项目中的Web.config,让我困惑了好久,最后在一个英文网页中找到的答案……。

        修改后的内容如下:

     <system.serviceModel>
      <behaviors>
       <serviceBehaviors>
        <behavior name="UploadFiles.Web.Service1Behavior">
         <serviceMetadata httpGetEnabled="true"/>
         <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
       </serviceBehaviors>
      </behaviors>
      <bindings>
       <customBinding>
        <binding name="customBinding0">
              <binaryMessageEncoding>
                <readerQuotas maxArrayLength="2097152"/><!--2MB-->
              </binaryMessageEncoding>
         <httpTransport maxReceivedMessageSize="2147483647"/>
        </binding>
       </customBinding>
      </bindings>
      <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
      <services>
       <service behaviorConfiguration="UploadFiles.Web.Service1Behavior" name="UploadFiles.Web.Service1">
        <endpoint address="" binding="customBinding" bindingConfiguration="customBinding0" contract="UploadFiles.Web.Service1"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
       </service>
      </services>
     </system.serviceModel>
    </configuration>

        修改的结果是允许最大2MB的数据块上传。Sunpire网友(参见参考文献2)提到的要增加24KB冗余的问题,我在实测中没有遇到。即:Sunpire网友的文章中提到<customBinding>要设置2MB+24KB,才能上传2MB数据的情况我没有遇到。我实际设置2MB就能上传2MB数据。当然,我没有象Sunpire网友那样去做那么多测试,只做了1MB和2MB的测试。

        6. 总结

        按照上述方法,可以实现各种文件快速上传。小文件上传几乎是瞬间的事,大文件也很快。

        缺点:上传时会一次性的把整个文件读入内存。进一步的解决方案是边读边上传。

    参考文献:

    [1]agile 的《Silverlight 3 中使用WCF上传文件 (简单进度条展示)》:http://my.oschina.net/agile/blog/2130

    [2]Sunpire 的《Silverlight+WCF文件上传,含分段大小调节(WCF 16KB配置)、压缩Buffer调节、速度指示、批量等》:http://www.soaspx.com/dotnet/silverlight/silverlight_20100321_3357.html

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yuvmen/archive/2010/04/23/5518244.aspx

  • 相关阅读:
    忘记IBM服务器的登录IP
    分层思想
    防火墙的发展历史
    存储相关
    HCIE_交换篇_ARP欺骗
    堡垒机与网闸
    防止ARP欺骗
    信息安全等级保护
    DPM如何创建存储池?
    Lync2013的会话
  • 原文地址:https://www.cnblogs.com/zcy_soft/p/1822344.html
Copyright © 2011-2022 走看看