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:

<UserControl x:Class="RichEdit.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    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">
    <UserControl.Resources>
        <ResourceDictionary>
            <dxre:RichEditUICommand x:Key="commands" />
            <dxre:RichEditStringIdConverter x:Key="stringIdConverter" />
        </ResourceDictionary>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <dxb:BarManager Name="barManager1" ToolbarGlyphSize="Small">
            <dxb:BarManager.Items>
                <dxb:BarButtonItem Command="{Binding Path=FileNew, Mode=OneTime, Source={StaticResource commands}}" Name="biFileNew" />
                <dxb:BarButtonItem Command="{Binding Path=FileSaveAs, Mode=OneTime, Source={StaticResource commands}}" Name="biFileSaveAs" />
                <dxb:BarButtonItem Command="{Binding Path=FilePrint, Mode=OneTime, Source={StaticResource commands}}" Name="biFilePrint" />
                <dxb:BarButtonItem Command="{Binding Path=FilePrintPreview, Mode=OneTime, Source={StaticResource commands}}" Name="biFilePrintPreview" />
                <dxb:BarButtonItem Command="{Binding Path=FileBrowserPrint, Mode=OneTime, Source={StaticResource commands}}" Name="biFileBrowserPrint" />
                <dxb:BarButtonItem Command="{Binding Path=FileBrowserPrintPreview, Mode=OneTime, Source={StaticResource commands}}" Name="biFileBrowserPrintPreview" />
                <dxb:BarButtonItem Command="{Binding Path=EditUndo, Mode=OneTime, Source={StaticResource commands}}" Name="biEditUndo" />
                <dxb:BarButtonItem Command="{Binding Path=EditRedo, Mode=OneTime, Source={StaticResource commands}}" Name="biEditRedo" />
                <dxb:BarButtonItem Content="LoadFromWeb" Name="barButtonItemLoad" Glyph="/RichEdit;component/Images/Chrysanthemum.jpg" ItemClick="barButtonItemLoad_ItemClick" GlyphAlignment="Top" GlyphSize="Default" />
                <dxb:BarButtonItem Name="barButtonItemSave" Glyph="/RichEdit;component/Images/Desert.jpg" Content="SaveToWeb" ItemClick="barButtonItemSave_ItemClick" />
                <dxb:BarStaticItem Content="message..." Name="barStaticItemMsg" />
            </dxb:BarManager.Items>
            <dx:DockPanel>
                <dxr:RibbonControl dx:DockPanel.Dock="Top" Name="ribbonControl1">
                    <dxr:RibbonControl.ApplicationMenu>
                        <dxr:ApplicationMenuInfo />
                    </dxr:RibbonControl.ApplicationMenu>
                    <dxr:RibbonDefaultPageCategory>
                        <dxr:RibbonPage Caption="{Binding Source={StaticResource stringIdConverter}, ConverterParameter=Caption_PageFile, Converter={StaticResource stringIdConverter}, Mode=OneTime}" Name="pageFile">
                            <dxr:RibbonPageGroup Caption="{Binding Source={StaticResource stringIdConverter}, ConverterParameter=Caption_GroupCommon, Converter={StaticResource stringIdConverter}, Mode=OneTime}" Name="grpCommon" ShowCaptionButton="False">
                                <dxb:BarButtonItemLink BarItemName="biFileNew" />
                                <dxb:BarButtonItemLink BarItemName="biFileSaveAs" />
                                <dxb:BarButtonItemLink BarItemName="biFilePrint" />
                                <dxb:BarButtonItemLink BarItemName="biFilePrintPreview" />
                                <dxb:BarButtonItemLink BarItemName="biFileBrowserPrint" />
                                <dxb:BarButtonItemLink BarItemName="biFileBrowserPrintPreview" />
                                <dxb:BarButtonItemLink BarItemName="biEditUndo" />
                                <dxb:BarButtonItemLink BarItemName="biEditRedo" />
                            </dxr:RibbonPageGroup>
                            <dxr:RibbonPageGroup Caption="Ribbon Page Group 1" Name="ribbonPageGroup1">
                                <dxb:BarButtonItemLink BarItemName="barButtonItemLoad" />
                                <dxb:BarButtonItemLink BarItemName="barButtonItemSave" />
                            </dxr:RibbonPageGroup>
                            <dxr:RibbonPageGroup Caption="Ribbon Page Group 2" Name="ribbonPageGroup2">
                                <dxb:BarStaticItemLink BarItemName="barStaticItemMsg" />
                            </dxr:RibbonPageGroup>
                        </dxr:RibbonPage>
                    </dxr:RibbonDefaultPageCategory>
                </dxr:RibbonControl>
                <dxre:RichEditControl Name="richEditControl1" BarManager="{Binding ElementName=barManager1, Mode=OneTime}" Ribbon="{Binding ElementName=ribbonControl1, Mode=OneTime}" />
            </dx:DockPanel>
        </dxb:BarManager>
    </Grid>
</UserControl>

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using DevExpress.XtraRichEdit;
using System.Threading;

namespace RichEdit
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        String uri = "http://localhost:8888/upload/UploadServlet";

        private void barButtonItemLoad_ItemClick(object sender, DevExpress.Xpf.Bars.ItemClickEventArgs e)
        {
            MessageBox.Show("Load Begin");

            ServerStreamLoad ssl = new ServerStreamLoad();
            ssl.Rp = new ShowLoadResultDelegate(ShowLoadResult);
            ssl.Load(uri);
        }

        private void barButtonItemSave_ItemClick(object sender, DevExpress.Xpf.Bars.ItemClickEventArgs e)
        {
            MessageBox.Show("Save Begin");

            WebRequest request = WebRequest.Create(new Uri(uri));

            Dictionary<String, String> nvc = new Dictionary<String, String>();
            nvc.Add("name", "value");
            nvc.Add("name1", "value1");

            ServerStreamSave sss = new ServerStreamSave();
            sss.Rp = new ShowSaveResultDelegate(ShowSaveResult);

            Stream stream = new MemoryStream();
            this.richEditControl1.SaveDocument(stream, DocumentFormat.Rtf);
            sss.Save(request, nvc, stream);
        }

        // 处理Load结果
        public void ShowLoadResult(Stream stream)
        {
            String msg = "OK";
            if (this.barStaticItemMsg.CheckAccess())
            {
                this.barStaticItemMsg.Content = msg;
            }
            else
            {
                Dispatcher.BeginInvoke(() =>
                {
                    this.barStaticItemMsg.Content = msg;
                });
            }

            using (stream)
            {
                if (this.richEditControl1.CheckAccess())
                {
                    this.richEditControl1.LoadDocument(stream, DocumentFormat.Rtf);
                }
                else
                {
                    Dispatcher.BeginInvoke(() =>
                    {
                        this.richEditControl1.LoadDocument(stream, DocumentFormat.Rtf);
                    });
                }
            }
        }

        // 处理Save结果
        public void ShowSaveResult(String msg)
        {
            if (this.barStaticItemMsg.CheckAccess())
            {
                this.barStaticItemMsg.Content = msg;
            }
            else
            {
                Dispatcher.BeginInvoke(() =>
                {
                    this.barStaticItemMsg.Content = msg;
                });
            }
        }
    }

    // 处理结果的委托
    public delegate void ShowLoadResultDelegate(Stream stream);
    public delegate void ShowSaveResultDelegate(String s);
}

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

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;

namespace RichEdit
{
    public class ServerStreamLoad
    {
        ShowLoadResultDelegate rp;

        public ShowLoadResultDelegate Rp
        {
            get { return rp; }
            set { rp = value; }
        }

        public void Load(String uri)
        {
            WebClient webClient = new WebClient();
            webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(LoadCompletedCallBack);
            webClient.OpenReadAsync(new Uri(uri));
        }

        private void LoadCompletedCallBack(object sender, OpenReadCompletedEventArgs e)
        {
            using (Stream stream = e.Result)
            {
                // read stream here
                rp(stream);
            }
        }
    }
}

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

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.Collections.Generic;
using System.Windows.Threading;

namespace RichEdit
{
    public class ServerStreamSave
    {
        static ShowSaveResultDelegate rp;

        public ShowSaveResultDelegate Rp
        {
            get { return rp; }
            set { rp = value; }
        }


        public void Save(WebRequest request, Dictionary<String, String> nvc, Stream stream)
        {
            request.Method = "POST";

            UploadState us = new UploadState();
            us.Req = request;
            us.Nvc = nvc;
            us.Stream = stream;

            request.BeginGetRequestStream(new AsyncCallback(SaveRequestReadyCallBack), us);
        }

        private void SaveRequestReadyCallBack(IAsyncResult asyncResult)
        {
            string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
            byte[] boundarybytes = System.Text.Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");

            WebRequest request = ((UploadState)(asyncResult.AsyncState)).Req as WebRequest;
            request.ContentType = "multipart/form-data; boundary=" + boundary;
            request.UseDefaultCredentials = true;

            Stream rs = request.EndGetRequestStream(asyncResult);

            // 1.write boundery and key-value pairs
            string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
            IDictionary<String, String> nvc = ((UploadState)(asyncResult.AsyncState)).Nvc as IDictionary<String, String>;
            foreach (string key in nvc.Keys)
            {
                rs.Write(boundarybytes, 0, boundarybytes.Length);
                string formitem = string.Format(formdataTemplate, key, nvc[key]);
                byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
                rs.Write(formitembytes, 0, formitembytes.Length);
            }

            rs.Write(boundarybytes, 0, boundarybytes.Length);

            // 2.write head
            string file = "file";
            string paramName = "file";
            string contentType = "unknown";

            string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
            string header = string.Format(headerTemplate, paramName, file, contentType);
            byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);

            rs.Write(headerbytes, 0, headerbytes.Length);

            // 3.write stream here,the stream will be closed by invoker
            using (Stream stream = ((UploadState)(asyncResult.AsyncState)).Stream as Stream)
            {
                stream.Position = 0;
                //byte[] buffer = System.Text.Encoding.UTF8.GetBytes("aaa我11");
                byte[] data = new byte[4096];

                int count = stream.Read(data, 0, 4096);
                while (count > 0)
                {
                    rs.Write(data, 0, count);
                    count = stream.Read(data, 0, 4096);
                }
            }

            //rs.Write(buffer, 0, buffer.Length);

            // 4.write trailer
            byte[] trailer = System.Text.Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");

            rs.Write(trailer, 0, trailer.Length);

            rs.Flush();
            rs.Close();

            request.BeginGetResponse(new AsyncCallback(SaveResponseReadyCallBack), request);
        }

        private void SaveResponseReadyCallBack(IAsyncResult asyncResult)
        {
            WebRequest request = asyncResult.AsyncState as WebRequest;
            WebResponse response = request.EndGetResponse(asyncResult);

            using (Stream responseStream = response.GetResponseStream())
            {
                StreamReader reader = new StreamReader(responseStream);

                // check response result by return msg.
                String msg = reader.ReadToEnd();

                rp(msg);
            }
        }
    }
}

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

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections;
using System.Collections.Generic;
using System.IO;

namespace RichEdit
{
    public class UploadState
    {
        IDictionary<String, String> nvc = null;

        public IDictionary<String, String> Nvc
        {
            get { return nvc; }
            set { nvc = value; }
        }

        WebRequest req = null;

        public WebRequest Req
        {
            get { return req; }
            set { req = value; }
        }

        Stream stream;

        public Stream Stream
        {
            get { return stream; }
            set { stream = value; }
        }
    }
}

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

1、web.xml配置:

	<servlet>
		<display-name>UploadServlet</display-name>
		<servlet-name>UploadServlet</servlet-name>
		<servlet-class>com.liyj.upload.servlet.UploadServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>UploadServlet</servlet-name>
		<url-pattern>/UploadServlet</url-pattern>
	</servlet-mapping>

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

package com.liyj.upload.servlet;

import java.io.*;
import java.util.List;

import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class UploadServlet extends HttpServlet {
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response) {
		ServletOutputStream out = null;
		
		System.out.println("into doGet..");
		
		try {
			out = response.getOutputStream();
			
			FileInputStream fis = new FileInputStream("D:\\file");
			
			byte[] data = new byte[4096];
			
			int count = fis.read(data);
			while(count > 0) {
				out.write(data, 0, count);
				count = fis.read(data);
			}
			
			fis.close();
			out.flush();
			out.close();
		} catch (Exception e)
		{
			e.printStackTrace();
		}		
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response) {
		ServletOutputStream out = null;
		System.out.println("into doPost..");
		DiskFileItemFactory factory = new DiskFileItemFactory();
        String path = "D:\\";
        factory.setRepository(new File(path));
        factory.setSizeThreshold(1024 * 1024);
        ServletFileUpload upload = new ServletFileUpload(factory);
        
        try {
        	out = response.getOutputStream();
        	
            List<FileItem> list = upload.parseRequest(request);
            for (FileItem item : list) {
                if (item.isFormField()) {
                    String name = item.getFieldName();
                    String value = item.getString("gbk");

                    out.println(name + ":" + value);
                } else {
                    String name = item.getFieldName();
                    String value = item.getName();
                    int start = value.lastIndexOf("\\");
                    String fileName = value.substring(start + 1);
                    //request.setAttribute(name, fileName);
                    
                    OutputStream os = new FileOutputStream(new File(path, fileName));
                    InputStream is = item.getInputStream();
                    byte[] buffer = new byte[1024];
                    int length = 0;
                    int fileLen = 0;
                    while ((length = is.read(buffer)) > 0) {
                        os.write(buffer, 0, length);
                        fileLen += length;
                    }
                    out.println("OK");
                    os.close();
                    is.close();
                }
            }
        } catch (Exception e) {
        	try {
				out.println("NG");
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
            e.printStackTrace();
        }
	}
}
---------- THE END-----------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值