天天看點

Silverlight技術調查(4)——完成的調查結果

用戶端使用Silverlight+DXperience,可以線上編輯各種常見文本及富文本文檔(doc、docx、rtf、txt、html……),Silverlight使用了異步送出和響應(通過WebClient和WebRequest),送出時,自行編排HTTP請求格式(請參見相應RFC标準);編輯的資料流上傳至Servlet後,Servlet使用commons-fileupload-1.2.2解包資料,擷取附加的請求參數及附件内容。

程式效果:

Silverlight技術調查(4)——完成的調查結果

下面為用戶端和伺服器端程式:

(一)用戶端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 Caption="Ribbon Page Group 2" Name="ribbonPageGroup2">  

                                <dxb:BarStaticItemLink BarItemName="barStaticItemMsg" />  

                        </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)  

    }  

    // 處理結果的委托  

    public delegate void ShowLoadResultDelegate(Stream stream);  

    public delegate void ShowSaveResultDelegate(String s);  

}  

3、資料流異步下載下傳部分ServerStreamLoad.cs:

using System.Windows.Ink;  

    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.Windows.Threading;  

    public class ServerStreamSave  

        static ShowSaveResultDelegate rp;  

        public ShowSaveResultDelegate Rp  

        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.Collections;  

    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>  

    <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) {  

        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);  

            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 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();  

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