原文 Silverlight技术调查(4)——完成的调查结果

客户端使用Silverlight+DXperience,可以在线编辑各种常见文本及富文本文档(doc、docx、rtf、txt、html……),Silverlight使用了异步提交和响应(通过WebClient和WebRequest),提交时,自行编排HTTP请求格式(请参见相应RFC标准);编辑的数据流上传至Servlet后,Servlet使用commons-fileupload-1.2.2解包数据,获取附加的请求参数及附件内容。

程序效果:

下面为客户端和服务器端程序:

(一)客户端Silverlight由部分组成:

1、主程序画面Layout部分MainPage.xaml:

  1. <UserControl x:Class="RichEdit.MainPage"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6. mc:Ignorable="d"
  7. d:DesignHeight="300" d:DesignWidth="400" xmlns:dxre="http://schemas.devexpress.com/winfx/2008/xaml/richedit" xmlns:dxb="http://schemas.devexpress.com/winfx/2008/xaml/bars" xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core" xmlns:dxr="http://schemas.devexpress.com/winfx/2008/xaml/ribbon">
  8. <UserControl.Resources>
  9. <ResourceDictionary>
  10. <dxre:RichEditUICommand x:Key="commands" />
  11. <dxre:RichEditStringIdConverter x:Key="stringIdConverter" />
  12. </ResourceDictionary>
  13. </UserControl.Resources>
  14. <Grid x:Name="LayoutRoot" Background="White">
  15. <dxb:BarManager Name="barManager1" ToolbarGlyphSize="Small">
  16. <dxb:BarManager.Items>
  17. <dxb:BarButtonItem Command="{Binding Path=FileNew, Mode=OneTime, Source={StaticResource commands}}" Name="biFileNew" />
  18. <dxb:BarButtonItem Command="{Binding Path=FileSaveAs, Mode=OneTime, Source={StaticResource commands}}" Name="biFileSaveAs" />
  19. <dxb:BarButtonItem Command="{Binding Path=FilePrint, Mode=OneTime, Source={StaticResource commands}}" Name="biFilePrint" />
  20. <dxb:BarButtonItem Command="{Binding Path=FilePrintPreview, Mode=OneTime, Source={StaticResource commands}}" Name="biFilePrintPreview" />
  21. <dxb:BarButtonItem Command="{Binding Path=FileBrowserPrint, Mode=OneTime, Source={StaticResource commands}}" Name="biFileBrowserPrint" />
  22. <dxb:BarButtonItem Command="{Binding Path=FileBrowserPrintPreview, Mode=OneTime, Source={StaticResource commands}}" Name="biFileBrowserPrintPreview" />
  23. <dxb:BarButtonItem Command="{Binding Path=EditUndo, Mode=OneTime, Source={StaticResource commands}}" Name="biEditUndo" />
  24. <dxb:BarButtonItem Command="{Binding Path=EditRedo, Mode=OneTime, Source={StaticResource commands}}" Name="biEditRedo" />
  25. <dxb:BarButtonItem Content="LoadFromWeb" Name="barButtonItemLoad" Glyph="/RichEdit;component/Images/Chrysanthemum.jpg" ItemClick="barButtonItemLoad_ItemClick" GlyphAlignment="Top" GlyphSize="Default" />
  26. <dxb:BarButtonItem Name="barButtonItemSave" Glyph="/RichEdit;component/Images/Desert.jpg" Content="SaveToWeb" ItemClick="barButtonItemSave_ItemClick" />
  27. <dxb:BarStaticItem Content="message..." Name="barStaticItemMsg" />
  28. </dxb:BarManager.Items>
  29. <dx:DockPanel>
  30. <dxr:RibbonControl dx:DockPanel.Dock="Top" Name="ribbonControl1">
  31. <dxr:RibbonControl.ApplicationMenu>
  32. <dxr:ApplicationMenuInfo />
  33. </dxr:RibbonControl.ApplicationMenu>
  34. <dxr:RibbonDefaultPageCategory>
  35. <dxr:RibbonPage Caption="{Binding Source={StaticResource stringIdConverter}, ConverterParameter=Caption_PageFile, Converter={StaticResource stringIdConverter}, Mode=OneTime}" Name="pageFile">
  36. <dxr:RibbonPageGroup Caption="{Binding Source={StaticResource stringIdConverter}, ConverterParameter=Caption_GroupCommon, Converter={StaticResource stringIdConverter}, Mode=OneTime}" Name="grpCommon" ShowCaptionButton="False">
  37. <dxb:BarButtonItemLink BarItemName="biFileNew" />
  38. <dxb:BarButtonItemLink BarItemName="biFileSaveAs" />
  39. <dxb:BarButtonItemLink BarItemName="biFilePrint" />
  40. <dxb:BarButtonItemLink BarItemName="biFilePrintPreview" />
  41. <dxb:BarButtonItemLink BarItemName="biFileBrowserPrint" />
  42. <dxb:BarButtonItemLink BarItemName="biFileBrowserPrintPreview" />
  43. <dxb:BarButtonItemLink BarItemName="biEditUndo" />
  44. <dxb:BarButtonItemLink BarItemName="biEditRedo" />
  45. </dxr:RibbonPageGroup>
  46. <dxr:RibbonPageGroup Caption="Ribbon Page Group 1" Name="ribbonPageGroup1">
  47. <dxb:BarButtonItemLink BarItemName="barButtonItemLoad" />
  48. <dxb:BarButtonItemLink BarItemName="barButtonItemSave" />
  49. </dxr:RibbonPageGroup>
  50. <dxr:RibbonPageGroup Caption="Ribbon Page Group 2" Name="ribbonPageGroup2">
  51. <dxb:BarStaticItemLink BarItemName="barStaticItemMsg" />
  52. </dxr:RibbonPageGroup>
  53. </dxr:RibbonPage>
  54. </dxr:RibbonDefaultPageCategory>
  55. </dxr:RibbonControl>
  56. <dxre:RichEditControl Name="richEditControl1" BarManager="{Binding ElementName=barManager1, Mode=OneTime}" Ribbon="{Binding ElementName=ribbonControl1, Mode=OneTime}" />
  57. </dx:DockPanel>
  58. </dxb:BarManager>
  59. </Grid>
  60. </UserControl>

2、主程序逻辑部分MainPage.xaml.cs:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Documents;
  8. using System.Windows.Input;
  9. using System.Windows.Media;
  10. using System.Windows.Media.Animation;
  11. using System.Windows.Shapes;
  12. using System.IO;
  13. using DevExpress.XtraRichEdit;
  14. using System.Threading;
  15. namespace RichEdit
  16. {
  17. public partial class MainPage : UserControl
  18. {
  19. public MainPage()
  20. {
  21. InitializeComponent();
  22. }
  23. String uri = "http://localhost:8888/upload/UploadServlet";
  24. private void barButtonItemLoad_ItemClick(object sender, DevExpress.Xpf.Bars.ItemClickEventArgs e)
  25. {
  26. MessageBox.Show("Load Begin");
  27. ServerStreamLoad ssl = new ServerStreamLoad();
  28. ssl.Rp = new ShowLoadResultDelegate(ShowLoadResult);
  29. ssl.Load(uri);
  30. }
  31. private void barButtonItemSave_ItemClick(object sender, DevExpress.Xpf.Bars.ItemClickEventArgs e)
  32. {
  33. MessageBox.Show("Save Begin");
  34. WebRequest request = WebRequest.Create(new Uri(uri));
  35. Dictionary<String, String> nvc = new Dictionary<String, String>();
  36. nvc.Add("name", "value");
  37. nvc.Add("name1", "value1");
  38. ServerStreamSave sss = new ServerStreamSave();
  39. sss.Rp = new ShowSaveResultDelegate(ShowSaveResult);
  40. Stream stream = new MemoryStream();
  41. this.richEditControl1.SaveDocument(stream, DocumentFormat.Rtf);
  42. sss.Save(request, nvc, stream);
  43. }
  44. // 处理Load结果
  45. public void ShowLoadResult(Stream stream)
  46. {
  47. String msg = "OK";
  48. if (this.barStaticItemMsg.CheckAccess())
  49. {
  50. this.barStaticItemMsg.Content = msg;
  51. }
  52. else
  53. {
  54. Dispatcher.BeginInvoke(() =>
  55. {
  56. this.barStaticItemMsg.Content = msg;
  57. });
  58. }
  59. using (stream)
  60. {
  61. if (this.richEditControl1.CheckAccess())
  62. {
  63. this.richEditControl1.LoadDocument(stream, DocumentFormat.Rtf);
  64. }
  65. else
  66. {
  67. Dispatcher.BeginInvoke(() =>
  68. {
  69. this.richEditControl1.LoadDocument(stream, DocumentFormat.Rtf);
  70. });
  71. }
  72. }
  73. }
  74. // 处理Save结果
  75. public void ShowSaveResult(String msg)
  76. {
  77. if (this.barStaticItemMsg.CheckAccess())
  78. {
  79. this.barStaticItemMsg.Content = msg;
  80. }
  81. else
  82. {
  83. Dispatcher.BeginInvoke(() =>
  84. {
  85. this.barStaticItemMsg.Content = msg;
  86. });
  87. }
  88. }
  89. }
  90. // 处理结果的委托
  91. public delegate void ShowLoadResultDelegate(Stream stream);
  92. public delegate void ShowSaveResultDelegate(String s);
  93. }

3、数据流异步下载部分ServerStreamLoad.cs:

  1. using System;
  2. using System.Net;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using System.Windows.Documents;
  6. using System.Windows.Ink;
  7. using System.Windows.Input;
  8. using System.Windows.Media;
  9. using System.Windows.Media.Animation;
  10. using System.Windows.Shapes;
  11. using System.IO;
  12. namespace RichEdit
  13. {
  14. public class ServerStreamLoad
  15. {
  16. ShowLoadResultDelegate rp;
  17. public ShowLoadResultDelegate Rp
  18. {
  19. get { return rp; }
  20. set { rp = value; }
  21. }
  22. public void Load(String uri)
  23. {
  24. WebClient webClient = new WebClient();
  25. webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(LoadCompletedCallBack);
  26. webClient.OpenReadAsync(new Uri(uri));
  27. }
  28. private void LoadCompletedCallBack(object sender, OpenReadCompletedEventArgs e)
  29. {
  30. using (Stream stream = e.Result)
  31. {
  32. // read stream here
  33. rp(stream);
  34. }
  35. }
  36. }
  37. }

4、数据流异步提交部分:

  1. using System;
  2. using System.Net;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using System.Windows.Documents;
  6. using System.Windows.Ink;
  7. using System.Windows.Input;
  8. using System.Windows.Media;
  9. using System.Windows.Media.Animation;
  10. using System.Windows.Shapes;
  11. using System.IO;
  12. using System.Collections.Generic;
  13. using System.Windows.Threading;
  14. namespace RichEdit
  15. {
  16. public class ServerStreamSave
  17. {
  18. static ShowSaveResultDelegate rp;
  19. public ShowSaveResultDelegate Rp
  20. {
  21. get { return rp; }
  22. set { rp = value; }
  23. }
  24. public void Save(WebRequest request, Dictionary<String, String> nvc, Stream stream)
  25. {
  26. request.Method = "POST";
  27. UploadState us = new UploadState();
  28. us.Req = request;
  29. us.Nvc = nvc;
  30. us.Stream = stream;
  31. request.BeginGetRequestStream(new AsyncCallback(SaveRequestReadyCallBack), us);
  32. }
  33. private void SaveRequestReadyCallBack(IAsyncResult asyncResult)
  34. {
  35. string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
  36. byte[] boundarybytes = System.Text.Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");
  37. WebRequest request = ((UploadState)(asyncResult.AsyncState)).Req as WebRequest;
  38. request.ContentType = "multipart/form-data; boundary=" + boundary;
  39. request.UseDefaultCredentials = true;
  40. Stream rs = request.EndGetRequestStream(asyncResult);
  41. // 1.write boundery and key-value pairs
  42. string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
  43. IDictionary<String, String> nvc = ((UploadState)(asyncResult.AsyncState)).Nvc as IDictionary<String, String>;
  44. foreach (string key in nvc.Keys)
  45. {
  46. rs.Write(boundarybytes, 0, boundarybytes.Length);
  47. string formitem = string.Format(formdataTemplate, key, nvc[key]);
  48. byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
  49. rs.Write(formitembytes, 0, formitembytes.Length);
  50. }
  51. rs.Write(boundarybytes, 0, boundarybytes.Length);
  52. // 2.write head
  53. string file = "file";
  54. string paramName = "file";
  55. string contentType = "unknown";
  56. string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
  57. string header = string.Format(headerTemplate, paramName, file, contentType);
  58. byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
  59. rs.Write(headerbytes, 0, headerbytes.Length);
  60. // 3.write stream here,the stream will be closed by invoker
  61. using (Stream stream = ((UploadState)(asyncResult.AsyncState)).Stream as Stream)
  62. {
  63. stream.Position = 0;
  64. //byte[] buffer = System.Text.Encoding.UTF8.GetBytes("aaa我11");
  65. byte[] data = new byte[4096];
  66. int count = stream.Read(data, 0, 4096);
  67. while (count > 0)
  68. {
  69. rs.Write(data, 0, count);
  70. count = stream.Read(data, 0, 4096);
  71. }
  72. }
  73. //rs.Write(buffer, 0, buffer.Length);
  74. // 4.write trailer
  75. byte[] trailer = System.Text.Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
  76. rs.Write(trailer, 0, trailer.Length);
  77. rs.Flush();
  78. rs.Close();
  79. request.BeginGetResponse(new AsyncCallback(SaveResponseReadyCallBack), request);
  80. }
  81. private void SaveResponseReadyCallBack(IAsyncResult asyncResult)
  82. {
  83. WebRequest request = asyncResult.AsyncState as WebRequest;
  84. WebResponse response = request.EndGetResponse(asyncResult);
  85. using (Stream responseStream = response.GetResponseStream())
  86. {
  87. StreamReader reader = new StreamReader(responseStream);
  88. // check response result by return msg.
  89. String msg = reader.ReadToEnd();
  90. rp(msg);
  91. }
  92. }
  93. }
  94. }

5、异步请求提交,回调封装参数部分UploadState.cs:

  1. using System;
  2. using System.Net;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using System.Windows.Documents;
  6. using System.Windows.Ink;
  7. using System.Windows.Input;
  8. using System.Windows.Media;
  9. using System.Windows.Media.Animation;
  10. using System.Windows.Shapes;
  11. using System.Collections;
  12. using System.Collections.Generic;
  13. using System.IO;
  14. namespace RichEdit
  15. {
  16. public class UploadState
  17. {
  18. IDictionary<String, String> nvc = null;
  19. public IDictionary<String, String> Nvc
  20. {
  21. get { return nvc; }
  22. set { nvc = value; }
  23. }
  24. WebRequest req = null;
  25. public WebRequest Req
  26. {
  27. get { return req; }
  28. set { req = value; }
  29. }
  30. Stream stream;
  31. public Stream Stream
  32. {
  33. get { return stream; }
  34. set { stream = value; }
  35. }
  36. }
  37. }

(二)服务器端使用commons-fileupload-1.2.2.jar实现上传:

1、web.xml配置:

  1. <servlet>
  2. <display-name>UploadServlet</display-name>
  3. <servlet-name>UploadServlet</servlet-name>
  4. <servlet-class>com.liyj.upload.servlet.UploadServlet</servlet-class>
  5. </servlet>
  6. <servlet-mapping>
  7. <servlet-name>UploadServlet</servlet-name>
  8. <url-pattern>/UploadServlet</url-pattern>
  9. </servlet-mapping>

2、UploadServlet.java(取打包的参数和附件)

  1. package com.liyj.upload.servlet;
  2. import java.io.*;
  3. import java.util.List;
  4. import javax.servlet.*;
  5. import javax.servlet.http.*;
  6. import org.apache.commons.fileupload.FileItem;
  7. import org.apache.commons.fileupload.FileUploadException;
  8. import org.apache.commons.fileupload.disk.DiskFileItemFactory;
  9. import org.apache.commons.fileupload.servlet.ServletFileUpload;
  10. public class UploadServlet extends HttpServlet {
  11. public void init(ServletConfig config) throws ServletException {
  12. super.init(config);
  13. }
  14. public void doGet(HttpServletRequest request, HttpServletResponse response) {
  15. ServletOutputStream out = null;
  16. System.out.println("into doGet..");
  17. try {
  18. out = response.getOutputStream();
  19. FileInputStream fis = new FileInputStream("D:\\file");
  20. byte[] data = new byte[4096];
  21. int count = fis.read(data);
  22. while(count > 0) {
  23. out.write(data, 0, count);
  24. count = fis.read(data);
  25. }
  26. fis.close();
  27. out.flush();
  28. out.close();
  29. } catch (Exception e)
  30. {
  31. e.printStackTrace();
  32. }
  33. }
  34. public void doPost(HttpServletRequest request, HttpServletResponse response) {
  35. ServletOutputStream out = null;
  36. System.out.println("into doPost..");
  37. DiskFileItemFactory factory = new DiskFileItemFactory();
  38. String path = "D:\\";
  39. factory.setRepository(new File(path));
  40. factory.setSizeThreshold(1024 * 1024);
  41. ServletFileUpload upload = new ServletFileUpload(factory);
  42. try {
  43. out = response.getOutputStream();
  44. List<FileItem> list = upload.parseRequest(request);
  45. for (FileItem item : list) {
  46. if (item.isFormField()) {
  47. String name = item.getFieldName();
  48. String value = item.getString("gbk");
  49. out.println(name + ":" + value);
  50. } else {
  51. String name = item.getFieldName();
  52. String value = item.getName();
  53. int start = value.lastIndexOf("\\");
  54. String fileName = value.substring(start + 1);
  55. //request.setAttribute(name, fileName);
  56. OutputStream os = new FileOutputStream(new File(path, fileName));
  57. InputStream is = item.getInputStream();
  58. byte[] buffer = new byte[1024];
  59. int length = 0;
  60. int fileLen = 0;
  61. while ((length = is.read(buffer)) > 0) {
  62. os.write(buffer, 0, length);
  63. fileLen += length;
  64. }
  65. out.println("OK");
  66. os.close();
  67. is.close();
  68. }
  69. }
  70. } catch (Exception e) {
  71. try {
  72. out.println("NG");
  73. } catch (IOException e1) {
  74. // TODO Auto-generated catch block
  75. e1.printStackTrace();
  76. }
  77. e.printStackTrace();
  78. }
  79. }
  80. }

---------- THE END-----------

Silverlight技术调查(4)——完成的调查结果的更多相关文章

  1. Silverlight技术调查(3)——国际化

    原文 Silverlight技术调查(3)——国际化 网上有很多关于Silverlight国际化的说明,包括MSDN的示例,都没有强调一点,下面以红色标示,基础国际化知识请先参考MSDN相关章节,关键 ...

  2. Silverlight技术调查(2)——跨域访问

    原文 Silverlight技术调查(2)——跨域访问 此调查web容器采用的是Tomcat,若允许所有域访问,只需在webapps下的根应用ROOT中,加入配置文件:clientaccesspoli ...

  3. Silverlight技术调查(1)——Html向Silverlight传参

    原文 Silverlight技术调查(1)——Html向Silverlight传参 近几日项目研究一个很牛的富文档编辑器DXperience RichEdit组件,调查环境为Silverlight4. ...

  4. Python技术调查

    1. IDE 2. Local Debugging & Remote Debugging 3. Profiling

  5. .NET Web开发技术简单整理

    在最初学习一些编程语言.一些编程技术的时候,做的更多的是如何使用该技术,如何更好的使用该技术解决问题,而没有去关注它的相关性.关注它的理论支持,这种学习技术的方式是短平快.其实工作中有时候也是这样,公 ...

  6. CTO和技术副总裁应该如何分工?谁才是技术领导者?

    谁是初创公司的技术领导者,是CTO还是技术副总裁?任何在创业公司工作的人都知道,我们不应该去问这个问题.因为这两个是非常不同的角色,角色本身会随着创业公司的发展而变化,两者对于业务规模都很重要. 简单 ...

  7. 使用SilverLight开发区域地图分析模块

    本人最近接收开发一个代码模块,功能主要是在页面上显示安徽省市地图,并且在鼠标移动到地图某市区域时,显示当前区域的各类信息等,一开始准备用百度地图,高德地图等地图工具进行开发,最后发现都不适合进行此类开 ...

  8. Silverlight开发工具汇总

    随着Silverlight技术的逐步完善,Silverlight应用大批的涌现,近期的2010年冬季奥运会,Silverlight作为首选视频播放技术,为全球提供在线赛事实况. Silverlight ...

  9. 转载:.NET Web开发技术简单整理

    在最初学习一些编程语言.一些编程技术的时候,做的更多的是如何使用该技术,如何更好的使用该技术解决问题,而没有去关注它的相关性.关注它的理论支持,这种学习技术的方式是短平快.其实工作中有时候也是这样,公 ...

随机推荐

  1. Strategic Game(匈牙利算法,最小点覆盖数)

    Strategic Game Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  2. android Graphics(一):概述及基本几何图形绘制

    前言:我最近想抽空研究研究android的各种特效,android的特效真是其它平台无法比拟的,而且一个漂亮的UI交互,会给APP增色不少,而学习特效之前,有关graphics绘图的基础知识是必不可少 ...

  3. 使用client对象模型回写SharePoint列表

    使用client对象模型回写SharePoint列表 client对象模型是一个有效的方式回写SharePoint列表. 1. 管理员身份打开VS,新建WPF应用程序SPWriteListApp,确保 ...

  4. 如何设置ssh安全只允许用户从指定的IP登陆

    原文链接: 如何设置ssh安全只允许用户从指定的IP登陆 由于开发上传文件需要  在服务器上开启  允许用户名和密码ssh登录.这样不太安全.百度后参考文章现在ssh用户名和密码登录的ip. 登录服务 ...

  5. [转]如何申请和管理一个sourceforge项目

    假如你没有贡献免费源代码的想法,就不用继续读本文了.:) 如果读者的e文不错,作者建议你直接阅读sourceforge的 howto文档,他们整理得非常周到详实.本文只是作者的使用经验,也许可以给与作 ...

  6. three.js 源代码凝视(十四)Math/Sphere.js

    商域无疆 (http://blog.csdn.net/omni360/) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:商域无疆 -  本博客专注于 敏捷开发 ...

  7. android 发送短信 怎样做到一条一条的发送,仅仅有在上一条发送成功之后才发送下一条短信

    android发送短信截获上一条发送是否成功,然后再来发送下一条短信 1.问题:在项目中遇到例如以下要求:待发短信有N条,实现一条一条的发送并在上一条短信发送成功之后再来发送下一条. for(int ...

  8. R语言RJava安装步骤

     1.安装JDK 2.在R下运行install.packages("rJava") 2.环境变量设置 CLASSPATH=xxx\R-xxx\library\rJava\jri ...

  9. JS - 按钮倒计时

    效果: html代码: <input type="button" id="btn" value="点击获取效验码" /> js代 ...

  10. Sql语句中使用参数化的Top

    在sql中使用参数化的Top,Top后面的参数要用括号括起来. 例如: select top (@ts) ID, [Type], Title, Content, LinkMan, Tel, Check ...