[网站]PlentyOfFish架构学习

mikel阅读(898)

这个叫PlentyOfFish网站,  它只有一个员工,每天只干两小时活,但是却被估值$1000000000

PlentyOfFish在山姆大叔家里算是一个很火的online dating网站,网站取名字来自这句话:There is plenty of fish in the sea. 对应的中文意思是天涯何处无芳草 Fish的意境虽然差了一点,但是却更加形象地表达了遍地撒网,中心钓鱼的泡妞的法则。 PlentyOfFish每个月有4500多万的访问用户,每天3000多万点击率。这个流量实际上并不夸张,平均算下来大概也就是500-600 request/s,峰值可能会更加高一点。在国内,我们可以发现douban.com就和它有的一拼,流量可能也差不了多少了。但是网站价值差多少倍偶就不知道了。通过和一般的互联网公司比较,大家可能认为这么流量也不小的公司怎么也要上百人左右,但它的确是只有一个干活的,这人就是Markus Frind。还有个非正式的好像是他女朋友,有时候帮他回回用户来信。当网站每个月能够收入4000块钱时候这个家伙就辞掉了全职工作,开始学着做SEO和竞价排名等等了。当我第一次访问这个网站的时候,第一感觉就是这也太土了把。但是或许正是因为它的土,它的默默无闻,使得没有人愿意去抄袭,去hack它。但有点我们得承认,Markus在网站内容和广告方面的确处理的很好,的确有不少值得我们学习的地方。

PlentyOfFish作为一个交友网站,我们或许并没有发现它有什么特殊的地方,也没有发现让人想尖叫的feature,但或许真是细节往往决定成败。它的成功的关键因素可能就是在基本功能方面能很符合用户的需要,在UE方面做的也比较贴心,同时也让用户能够坦然接受这个免费网站的UI的丑陋和服务的不稳定性,而更为愿意通过这个平台来发布一些内容,share一些个人图片,通过这个网站来找靓妞或者帅哥dating了。 PlentyOfFish允许它的用户上传很多照片,据统计已达到了6TB,然后允许每个用户可以对其它用户的照片进行打分,这中间的交互过程可能是给了用户带来很多自我表达的机会,使得他们开始沉迷于这个网站。PlentyOfFish在用户资料真实性方面做了很多工作,提供了各种举报和打假功能,估计站长每天就是在删除这些捣乱用户了。然而它的流行并不能阻止我们对那个1后面加很多0的估值的疑问?它凭什么值那么多美元?PlentyOfFish并没有收取任何注册用户的费用,而是宣称100% Free。那他到底怎么挣钱的呢?难道他有什么绝佳的盈利模式idea?实际上和我们很多人一样,就是仅仅靠网站打点广告,收点广告费。而我们加上阿里妈妈广告条,每个月只能给自己增加点零花钱,但是他现在一年可以从google Adsense混到1000万美元还多。TMD,眼红,口水直流…..而且这个数据应该已经过时了。一个站长能把一个网站推到如此规模,我不知道这个星球上还有没有一个可以和他比肩的人。有的话你让他站出来,偶马上跪拜在地……师傅,教我J……

Markus,他和我一样,不是我和他,呵呵,只会使用.Net,所以想做个网站,也只好从用ASP.NET开始了。正是这个网站的简单想法,使得一个具有传奇意义的互联网产品诞生了。至于Markus当时怎么bootstrap这个网站,以及怎么一步一步做大,我就不得而知了。PlentyOfFish的后台采用的技术和产品可能和我们大部分使用.Net的网站一样,下面我们就来一起简单分析一下它的后台架构。

·         Web框架和服务器:  ASP.NET+IIS+ Windows x64 Server 2003

·         Web Server 2 个做负载均衡的web servers , 基本配置是 2 Quad Core Intel    Xeon X5355 @ 2.66Ghz), 8 G RAM (使用了大约800 MBs), 2 hard drives

 

·         DB Server:  3SQL Server,采用master-slave架构,两台负责read操作,master那台负责写操作。这个和myspace早期的后台数据库架构是一样,看来这种架构很流行嘛。

·         Internet connection 1Gbps 使用了大概200Mbps

·         CDN: 使用了Akamai的服务,每天要传输1.7亿张图片

·         图片规模:6TB左右,数亿张图片

·         资源状态:Everything is dynamic. Nothing is static。没有使用ASP.NET内部cache机制,资源很快就Expire了。

·         压缩: 所有的request数据都使用了gzip压缩,大概耗费了30%CPU,但是降低了带宽成本。欧美的带宽不便宜。

·         Load Balance 使用了ServerIron ,而不是NLB(windows负载均衡解决方案) ServerIron NLB便宜而且简单很多。

·         Performance Monitor: Windows Task Manager,够牛

·         I/O操作: 因为内容很难cache,所以花了很多功夫在db performance tuning上。

·         MemoryCPU: 把最近常使用的图片直接放在内存中,所以内存会那么大;CPU配置也挺好,gzip是相当耗费CPU计算的。

Markus说他碰到问题基本上是IO操作方面的瓶颈,很少是被.Net block住。MarkusSessionFarm,以及数据库反范式等很多方面都有很不错的经验,很值得我们学习和借鉴,更多的细节大家可以参考后面的链接的几篇文章。

Markus最近也有了新的计划,他做了一些让POF进一步发展的计划:

·         盈利模式发生一些改变,不仅仅依靠google ads。希望从所有用户身上榨取更多的美元出来。

·         打算打造一个营销团队

·         观察竞争对手然后加入新的功能

·         考虑使用Amazon S3存储来达到地域分布式load balanced。就像建立多个data centers一样。主要可能是S3价格相当便宜。


作者:shawnliu

出处:http://www.cnblogs.com/liushouzhao

 

参考文章

PlentyOfFish Architecture

PlentyOfFish 网站架构学习

About PlentyofFish

[网站]PlentyOfFish网站架构学习

mikel阅读(724)

采取 Windows 技术路线的 Web 2.0 站点并不多,除了 MySpace ,另外就是这个 PlentyOfFish。这个站点提供 "Online Dating” 服务。一个令人津津乐道的、惊人的数据是这个只有一个人(创建人Markus Frind)的站点价值 10 亿,估计要让很多人眼热,更何况 Markus Frind 每天只用两个小时打理网站–可操作性很强嘛。

之所以选择 Windows .NET 的技术路线是因为 Markus Frind 不懂 LAMP 那一套东西,会啥用啥。就这样,也能支撑 超过 3000 万的日点击率(从这个数字也能看出来人类对自然天性的渴望是多迫切)。Todd Hoff 收集了很多关于 PlentyOfFish 架构的细节。记录一下感兴趣的部分。

带宽与CPU

PlentyOfFish 比较特殊的一个地方是 几乎不需要 Cache,因为数据变化过快,很快就过期。我不知道这是因为 ASP.NET 的特点带来的架构特点,还是业务就是这个样子的。至于图片,则是通过 CDN 支撑的。对于动态出站(outbound)的数据进行压缩,这耗费了 30% 的 CPU 能力,但节省了带宽资源。我最近才知道,欧美的带宽开销也不便宜。

负载均衡

微软 Windows 网络负载均衡(Network Load Balancing) 的一个缺陷是不能保持 Session 状态(我没有用过这玩意儿,不能确认),价格也不便宜,而且复杂;网络负载均衡对 Windows 架构的站点又是必须–IIS 的总连接数是有限制的。PlentyOfFish 用的是 ServerIron (Conf Refer),ServerIron 使用简单,而且功能比 NLB 更丰富。

数据库

一共三台 SQL Server,一台作为主库,另外两台只读数据库支撑查询。数据库性能监控用的是“Windows 任务管理器"。因为 Cache没啥用,所以要花大力气优化 DB。每个页面上调用 DB 次数越少越好,越简单越好,这是常识,不过不是每个人都体会那么深而已。

微软好不容易找到了一个宣传案例,所以在 Channel 9 上有一个 PlentyOfFish 的访谈

PlentyOfFish 取自天涯何处无芳草(Plenty of fish in the sea)的意思,还挺有文化的。从这一点上看,比国内那些拉皮条的网站好一些。

[C#]读写二进制文件

mikel阅读(965)

  1using System;
  2using System.Drawing;
  3using System.Collections;
  4using System.ComponentModel;
  5using System.Windows.Forms;
  6using System.Data;
  7// 添加新的命名空间。
  8using System.IO;
  9using System.Text;
 10
 11namespace BinaryFile
 12{
 13    /// <summary>
 14    /// 处理二进制文件。
 15    /// </summary>

 16    public class Form1 : System.Windows.Forms.Form
 17    {
 18        private System.Windows.Forms.Button button1;
 19        private System.Windows.Forms.RichTextBox richTextBox1;
 20        /// <summary>
 21        /// 必需的设计器变量。
 22        /// </summary>

 23        private System.ComponentModel.Container components = null;
 24
 25        public Form1()
 26        {
 27            // Windows 窗体设计器支持所必需的
 28            InitializeComponent();
 29            // TODO: 在 InitializeComponent 调用后添加任何构造函数代码
 30            // 写二进制文件
 31            s = File.Create("test.bin");
 32            w = new BinaryWriter(s);
 33            string str = "这是一行文字。\n";
 34            w.Write(str);
 35            float a = 3.1415F;
 36            w.Write(a);
 37            ulong b = 100000L;
 38            w.Write(b);
 39            int c = 300;
 40            w.Write(c);
 41            decimal d = 4.40983M;
 42            w.Write(d);
 43            double f = 94853.938485928d;
 44            w.Write(f);
 45            char[] g = {'h','e','l','l','o'};
 46            w.Write(g, 0, g.Length);
 47            char h = 'W';
 48            w.Write(h);
 49            bool i = true;
 50            w.Write(i);
 51            w.Flush();
 52            w.Close();
 53        }

 54
 55        /// <summary>
 56        /// 清理所有正在使用的资源。
 57        /// </summary>

 58        protected override void Dispose( bool disposing )
 59        {
 60            if( disposing )
 61            {
 62                if (components != null
 63                {
 64                    components.Dispose();
 65                }

 66            }

 67            base.Dispose( disposing );
 68        }

 69
 70        Windows Form Designer generated code
116
117        /// <summary>
118        /// 应用程序的主入口点。
119        /// </summary>

120        [STAThread]
121        static void Main() 
122        {
123            Application.Run(new Form1());
124        }

125        // 定义私有变量
126        public Stream s;
127        // 读二进制文件
128        public BinaryReader r;
129        // 写二进制文件
130        public BinaryWriter w;
131        // 显示二进制文件内容
132        private void button1_Click(object sender, System.EventArgs e)
133        {
134            s = File.OpenRead("test.bin");
135            r = new BinaryReader(s);
136            richTextBox1.Text  = "显示 String:";
137            richTextBox1.Text +=  r.ReadString();
138            richTextBox1.Text += "显示 Float:";
139            richTextBox1.Text += r.ReadSingle().ToString() + "\n";
140            richTextBox1.Text += "显示 ULong:";
141            richTextBox1.Text += r.ReadUInt64().ToString() + "\n";
142            richTextBox1.Text += "显示 Int:";
143            richTextBox1.Text += r.ReadInt32().ToString() + "\n";
144            richTextBox1.Text += "显示 Decimal:";
145            richTextBox1.Text += r.ReadDecimal().ToString() + "\n";
146            richTextBox1.Text += "显示 Double:";
147            richTextBox1.Text += r.ReadDouble().ToString() + "\n";
148            richTextBox1.Text += "显示 Char[]:";
149            richTextBox1.Text += Encoding.ASCII.GetString(r.ReadBytes(5)) + "\n";
150            richTextBox1.Text += "显示 Char:";
151            richTextBox1.Text += r.ReadChar().ToString() + "\n";
152            richTextBox1.Text += "显示 Boolean:";
153            richTextBox1.Text += r.ReadBoolean().ToString() + "\n";
154            r.Close();
155        }

156    }

157}

[JQuery]JScript读写二进制文件

mikel阅读(1012)

asp环境中,vbscript先天性的在读写二进制数据方面比JScript方便,JScript本身并无针对二进制数据(或者说字节数据)的数 据类型、对象、方法,所以有些高手爱用JScript写ASP,但是如果涉及字节数据处理基本上都要头痛。我在CodeProject.com上看到这篇 文章,觉得非常有用,所以转过来。基本原理就是用ADODB.Stream读写时指定为437代码页就可以以文本的形式来读写了。
原文网址: http://www.codeproject.com/KB/scripting/Exsead7.aspx

Reading And Writing Binary Files Using JScript

 

 By alex turner

An easy to use class that gives some binary file abilities to JScript

JavaScript, Windows, Visual Studio, Dev
Posted: 1 Mar 2007
Updated: 1 Mar 2007
Views: 9,885
Bookmarked: 5 times

 

Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

Introduction

As I have pushed what I can do in JScript, I have come up against the issue of binary files. The following class solved this for small to medium size files. I am partly including this post here because I am about to put in a post about sending emails with attachments via JScript and it will use this binary file code to read in the binary attachment files.

So, here is a nice way of accessing binary files from JScript. If you want to access this object from VBScript, then put it in a swf file. This object has been used in anger to upload files to a web service and has proven to be nice and fast for files in the 0-10 MByte region.

 

/** This is a fairly well optimized object which alows
  * access to binary files from JScript on a Windows
  * operating system.
  *
  * A the end of the file is small set of tests to show how it
  * is used.  You will require ADODB 2.5 or higher installed.
  * this will be so on most 2000 machines and all XP or higher
  * machines.
  *
  * CopyRight: Dr Alexander J Turner – all rights reserved.
  * Please feel free to use this code in any way you like
  * as long as you place a reference in the comments that
  * I wrote it.
  
*/
function BinaryFile(name)
{
    
var adTypeBinary = 1 
    
var adTypeText   = 2 
    
var adSaveCreateOverWrite = 2
    
// The trick – this is the 'old fassioned' not translation page

    
// It lest JavaScript use strings to act like raw octets

    
var codePage='437';
   
    
this.path=name;
   
    
var forward  = new Array();
    
var backward = new Array();
   
    
// Note – for better performance I should preconvert these hex

    
// definitions to decimal – at some point 🙂 – AJT

    forward[
'80'= '00C7';
    forward[
'81'= '00FC';
    forward[
'82'= '00E9';
    forward[
'83'= '00E2';
    forward[
'84'= '00E4';
    forward[
'85'= '00E0';
    forward[
'86'= '00E5';
    forward[
'87'= '00E7';
    forward[
'88'= '00EA';
    forward[
'89'= '00EB';
    forward[
'8A'= '00E8';
    forward[
'8B'= '00EF';
    forward[
'8C'= '00EE';
    forward[
'8D'= '00EC';
    forward[
'8E'= '00C4';
    forward[
'8F'= '00C5';
    forward[
'90'= '00C9';
    forward[
'91'= '00E6';
    forward[
'92'= '00C6';
    forward[
'93'= '00F4';
    forward[
'94'= '00F6';
    forward[
'95'= '00F2';
    forward[
'96'= '00FB';
    forward[
'97'= '00F9';
    forward[
'98'= '00FF';
    forward[
'99'= '00D6';
    forward[
'9A'= '00DC';
    forward[
'9B'= '00A2';
    forward[
'9C'= '00A3';
    forward[
'9D'= '00A5';
    forward[
'9E'= '20A7';
    forward[
'9F'= '0192';
    forward[
'A0'= '00E1';
    forward[
'A1'= '00ED';
    forward[
'A2'= '00F3';
    forward[
'A3'= '00FA';
    forward[
'A4'= '00F1';
    forward[
'A5'= '00D1';
    forward[
'A6'= '00AA';
    forward[
'A7'= '00BA';
    forward[
'A8'= '00BF';
    forward[
'A9'= '2310';
    forward[
'AA'= '00AC';
    forward[
'AB'= '00BD';
    forward[
'AC'= '00BC';
    forward[
'AD'= '00A1';
    forward[
'AE'= '00AB';
    forward[
'AF'= '00BB';
    forward[
'B0'= '2591';
    forward[
'B1'= '2592';
    forward[
'B2'= '2593';
    forward[
'B3'= '2502';
    forward[
'B4'= '2524';
    forward[
'B5'= '2561';
    forward[
'B6'= '2562';
    forward[
'B7'= '2556';
    forward[
'B8'= '2555';
    forward[
'B9'= '2563';
    forward[
'BA'= '2551';
    forward[
'BB'= '2557';
    forward[
'BC'= '255D';
    forward[
'BD'= '255C';
    forward[
'BE'= '255B';
    forward[
'BF'= '2510';
    forward[
'C0'= '2514';
    forward[
'C1'= '2534';
    forward[
'C2'= '252C';
    forward[
'C3'= '251C';
    forward[
'C4'= '2500';
    forward[
'C5'= '253C';
    forward[
'C6'= '255E';
    forward[
'C7'= '255F';
    forward[
'C8'= '255A';
    forward[
'C9'= '2554';
    forward[
'CA'= '2569';
    forward[
'CB'= '2566';
    forward[
'CC'= '2560';
    forward[
'CD'= '2550';
    forward[
'CE'= '256C';
    forward[
'CF'= '2567';
    forward[
'D0'= '2568';
    forward[
'D1'= '2564';
    forward[
'D2'= '2565';
    forward[
'D3'= '2559';
    forward[
'D4'= '2558';
    forward[
'D5'= '2552';
    forward[
'D6'= '2553';
    forward[
'D7'= '256B';
    forward[
'D8'= '256A';
    forward[
'D9'= '2518';
    forward[
'DA'= '250C';
    forward[
'DB'= '2588';
    forward[
'DC'= '2584';
    forward[
'DD'= '258C';
    forward[
'DE'= '2590';
    forward[
'DF'= '2580';
    forward[
'E0'= '03B1';
    forward[
'E1'= '00DF';
    forward[
'E2'= '0393';
    forward[
'E3'= '03C0';
    forward[
'E4'= '03A3';
    forward[
'E5'= '03C3';
    forward[
'E6'= '00B5';
    forward[
'E7'= '03C4';
    forward[
'E8'= '03A6';
    forward[
'E9'= '0398';
    forward[
'EA'= '03A9';
    forward[
'EB'= '03B4';
    forward[
'EC'= '221E';
    forward[
'ED'= '03C6';
    forward[
'EE'= '03B5';
    forward[
'EF'= '2229';
    forward[
'F0'= '2261';
    forward[
'F1'= '00B1';
    forward[
'F2'= '2265';
    forward[
'F3'= '2264';
    forward[
'F4'= '2320';
    forward[
'F5'= '2321';
    forward[
'F6'= '00F7';
    forward[
'F7'= '2248';
    forward[
'F8'= '00B0';
    forward[
'F9'= '2219';
    forward[
'FA'= '00B7';
    forward[
'FB'= '221A';
    forward[
'FC'= '207F';
    forward[
'FD'= '00B2';
    forward[
'FE'= '25A0';
    forward[
'FF'= '00A0';
    backward[
'C7']   = '80';
    backward[
'FC']   = '81';
    backward[
'E9']   = '82';
    backward[
'E2']   = '83';
    backward[
'E4']   = '84';
    backward[
'E0']   = '85';
    backward[
'E5']   = '86';
    backward[
'E7']   = '87';
    backward[
'EA']   = '88';
    backward[
'EB']   = '89';
    backward[
'E8']   = '8A';
    backward[
'EF']   = '8B';
    backward[
'EE']   = '8C';
    backward[
'EC']   = '8D';
    backward[
'C4']   = '8E';
    backward[
'C5']   = '8F';
    backward[
'C9']   = '90';
    backward[
'E6']   = '91';
    backward[
'C6']   = '92';
    backward[
'F4']   = '93';
    backward[
'F6']   = '94';
    backward[
'F2']   = '95';
    backward[
'FB']   = '96';
    backward[
'F9']   = '97';
    backward[
'FF']   = '98';
    backward[
'D6']   = '99';
    backward[
'DC']   = '9A';
    backward[
'A2']   = '9B';
    backward[
'A3']   = '9C';
    backward[
'A5']   = '9D';
    backward[
'20A7'= '9E';
    backward[
'192']  = '9F';
    backward[
'E1']   = 'A0';
    backward[
'ED']   = 'A1';
    backward[
'F3']   = 'A2';
    backward[
'FA']   = 'A3';
    backward[
'F1']   = 'A4';
    backward[
'D1']   = 'A5';
    backward[
'AA']   = 'A6';
    backward[
'BA']   = 'A7';
    backward[
'BF']   = 'A8';
    backward[
'2310'= 'A9';
    backward[
'AC']   = 'AA';
    backward[
'BD']   = 'AB';
    backward[
'BC']   = 'AC';
    backward[
'A1']   = 'AD';
    backward[
'AB']   = 'AE';
    backward[
'BB']   = 'AF';
    backward[
'2591'= 'B0';
    backward[
'2592'= 'B1';
    backward[
'2593'= 'B2';
    backward[
'2502'= 'B3';
    backward[
'2524'= 'B4';
    backward[
'2561'= 'B5';
    backward[
'2562'= 'B6';
    backward[
'2556'= 'B7';
    backward[
'2555'= 'B8';
    backward[
'2563'= 'B9';
    backward[
'2551'= 'BA';
    backward[
'2557'= 'BB';
    backward[
'255D'= 'BC';
    backward[
'255C'= 'BD';
    backward[
'255B'= 'BE';
    backward[
'2510'= 'BF';
    backward[
'2514'= 'C0';
    backward[
'2534'= 'C1';
    backward[
'252C'= 'C2';
    backward[
'251C'= 'C3';          
    backward[
'2500'= 'C4';
    backward[
'253C'= 'C5';
    backward[
'255E'= 'C6';
    backward[
'255F'= 'C7';
    backward[
'255A'= 'C8';
    backward[
'2554'= 'C9';
    backward[
'2569'= 'CA';
    backward[
'2566'= 'CB';
    backward[
'2560'= 'CC';
    backward[
'2550'= 'CD';
    backward[
'256C'= 'CE';
    backward[
'2567'= 'CF';
    backward[
'2568'= 'D0';
    backward[
'2564'= 'D1';
    backward[
'2565'= 'D2';
    backward[
'2559'= 'D3';
    backward[
'2558'= 'D4';
    backward[
'2552'= 'D5';
    backward[
'2553'= 'D6';
    backward[
'256B'= 'D7';
    backward[
'256A'= 'D8';
    backward[
'2518'= 'D9';
    backward[
'250C'= 'DA';
    backward[
'2588'= 'DB';
    backward[
'2584'= 'DC';
    backward[
'258C'= 'DD';
    backward[
'2590'= 'DE';
    backward[
'2580'= 'DF';
    backward[
'3B1']  = 'E0';
    backward[
'DF']   = 'E1';
    backward[
'393']  = 'E2';
    backward[
'3C0']  = 'E3';
    backward[
'3A3']  = 'E4';
    backward[
'3C3']  = 'E5';
    backward[
'B5']   = 'E6';
    backward[
'3C4']  = 'E7';
    backward[
'3A6']  = 'E8';
    backward[
'398']  = 'E9';
    backward[
'3A9']  = 'EA';
    backward[
'3B4']  = 'EB';                                                              
    backward[
'221E'= 'EC';
    backward[
'3C6']  = 'ED';
    backward[
'3B5']  = 'EE';
    backward[
'2229'= 'EF';
    backward[
'2261'= 'F0';
    backward[
'B1']   = 'F1';
    backward[
'2265'= 'F2';
    backward[
'2264'= 'F3';
    backward[
'2320'= 'F4';
    backward[
'2321'= 'F5';
    backward[
'F7']   = 'F6';
    backward[
'2248'= 'F7';
    backward[
'B0']   = 'F8';
    backward[
'2219'= 'F9';
    backward[
'B7']   = 'FA';
    backward[
'221A'= 'FB';
    backward[
'207F'= 'FC';
    backward[
'B2']   = 'FD';
    backward[
'25A0'= 'FE';
    backward[
'A0']   = 'FF';     
   
    
var hD="0123456789ABCDEF";
    
this.d2h = function(d)
    {
        
var h = hD.substr(d&15,1);
        
while(d>15) {d>>=4;h=hD.substr(d&15,1)+h;}
        
return h;
    }
    
this.h2d = function(h)
    {
        
return parseInt(h,16);
    }
   
    
this.WriteAll = function(what)
    {
        
//Create Stream object

        
var BinaryStream = WScript.CreateObject("ADODB.Stream");
        
//Specify stream type – we cheat and get string but 'like' binary

        BinaryStream.Type 
= adTypeText;
        BinaryStream.CharSet 
= '437';         
        
//Open the stream

        BinaryStream.Open();
        
// Write to the stream

        BinaryStream.WriteText(
this.Forward437(what));
        
// Write the string to the disk

        BinaryStream.SaveToFile(
this.path, adSaveCreateOverWrite);
        
// Clearn up

        BinaryStream.Close();
    }
   
    
this.ReadAll  = function()
    {
        
//Create Stream object – needs ADO 2.5 or heigher

        
var BinaryStream = WScript.CreateObject("ADODB.Stream")
        
//Specify stream type – we cheat and get string but 'like' binary

        BinaryStream.Type 
= adTypeText;
        BinaryStream.CharSet 
= codePage;
        
//Open the stream

        BinaryStream.Open();
        
//Load the file data from disk To stream object

        BinaryStream.LoadFromFile(
this.path);
        
//Open the stream And get binary 'string' from the object

        
var what = BinaryStream.ReadText;
        
// Clean up

        BinaryStream.Close();
        
return this.Backward437(what);
    }
   
    
/* Convert a octet number to a code page 437 char code */
    
this.Forward437 = function(inString)
    {
        
var encArray = new Array();
        
var tmp='';
        
var i=0;
        
var c=0;
        
var l=inString.length;
        
var cc;
        
var h;
        
for(;i<l;++i)
        {
            c
++;
            
if(c==128)
            {
                encArray.push(tmp);
                tmp
='';
                c
=0;
            }
            cc
=inString.charCodeAt(i);
            
if(cc<128)
            {
                tmp
+=String.fromCharCode(cc);
            }      
            
else
            {
                h
=this.d2h(cc);
                h
=forward[''+h];
                tmp
+=String.fromCharCode(this.h2d(h));
            }
        }
        
if(tmp!='')
        {
            encArray.push(tmp);
        }
        
// this loop progressive concatonates the

        
// array elements entil there is only one

        
var ar2=new Array();
        
for(;encArray.length>1😉
        {
            
var l=encArray.length;
            
for(var c=0;c<l;c+=2)
            {
                
if(c+1==l)
                {
                    ar2.push(encArray);
                }
                
else
                {
                    ar2.push(
''+encArray+encArray);
                }
            }
            encArray
=ar2;
            ar2
=new Array();
        }
        
return encArray[0];
    }
    
/* Convert a code page 437 char code to a octet number*/
    
this.Backward437 = function(inString)
    {
        
var encArray = new Array();
        
var tmp='';
        
var i=0;
        
var c=0;
        
var l=inString.length;
        
var cc;
        
var h;
        
for(;i<l;++i)
        {
            c
++;
            
if(c==128)
            {
                encArray.push(tmp);
                tmp
='';
                c
=0;
            }
            cc
=inString.charCodeAt(i);
            
if(cc<128)
            {
                tmp
+=String.fromCharCode(cc);
            }
            
else
            {
                h
=this.d2h(cc);
                h
=backward[''+h];
                tmp
+=String.fromCharCode(this.h2d(h));
            }
        }
        
if(tmp!='')
        {
            encArray.push(tmp);
        }
        
// this loop progressive concatonates the

        
// array elements entil there is only one

        
var ar2=new Array();
        
for(;encArray.length>1😉
        {
            
var l=encArray.length;
            
for(var c=0;c<l;c+=2)
            {
                
if(c+1==l)
                {
                    ar2.push(encArray);
                }
                
else
                {
                    ar2.push(
''+encArray+encArray);
                }
            }
            encArray
=ar2;
            ar2
=new Array();
        }
        
return encArray[0];
    }
   
}
// Example Code

/*
var bf0=new BinaryFile();
var crFolder = 'C:/Temp/cr'
var bf1=new BinaryFile(crFolder+"/PCDV0026.JPG");
var bf2=new BinaryFile(crFolder+"/PCDV0026_.JPG");
bf2.WriteAll(bf1.ReadAll());
*/

 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

alex turner
I started out as a Chemist, but just keep being pulled back into IT.
I am now a senior architect with The Project Network (www.project-network.com)

Occupation: Web Developer
Location:  United Kingdom

[Flash]Flash3D编程探秘一

mikel阅读(871)

作者:Yang Zhou
感谢:Crystal

介绍

对学习Flash中的3D编程感兴趣?那么你来对地方了。在这篇文章中,我将陆续的介绍在Flash中使用Actionsript进行3D编程一些实例。 这是一篇初级到中级难度的学习资料,如果你具有一些基本的几何知识,那对你来说不会太难。虽然例子中运用了非常简单的程序构架和实现方法,但是我还是期望 你已经有大量的Actionscirpt和Flash经验,这样你在使用以及理解Actionscript语言的时候不会有太大的障碍。如果你在阅读中发 现很多地方不清楚,或者这些对你来说是比较新的东西,那么我建议你参考我写过的另外几篇3D的基础知识的文章。

文章中含有大量的代码和一些算法的实现,在这里你可以完全拷贝我写的代码去使用,但是请务必注明出处。

 

点此下载本节源文件

 

Flash 和 3D空间

第一件事情我想你知道的是,在Flash里,并不存在真正的3D。我们所做的是运用Flash里的2D绘制方法去模拟3D绘制。或者我应该 说,Flash并不支持3D绘制,Flash并不知道3D是什么也不知道如何去处理3D对象。但是好消息是所有的3D处理和3D计算都是建立在数学计算的 基础上的,加上 Flash知道如何的处理数学计算。太好了,我们有了这些工具便可以创造出我们自己的动画了。这并不是说Flash里的3D编程要简单,如果你打算深入去 探索的话你会发现恰恰相反。不管怎样,在这篇文章中我会用最大的努力把数学部分变得简单。

在Flash里,有两种3D处理方式,一种是提前处理好3D模型,另外一种是在程序运行时通过数学计算处理3D图形。运用第一种方法,我们可以提前 处理好一系列的图形,然后通过对祯或者是时间进行动画播放,以达到3D效果。相对来说,第一种方法对美工的要求比较高。后一种方法我们通过大量的数学计算 对物体进行操作,这也是在这篇文章里所关心的。

 

3D程序

如今你在互联网上搜索3D Flash你会找到很多的工具和程序,利用这些程序你可以绘制一些3D图形并导出你需要的格式,甚至完全使用在你的项目里。基本上你可以不必操心如何绘制 3D图形。但是这些程序都是提前做好的模版,不能够作太多的编辑。于是我们发现我们自己也有大脑,我们自己也可以制作简单的缩放动画,还可以制作复杂的 3D绘制引擎。

毕竟我们是从最基础的2D绘制开始制作3D对象。这并不像我们在使用显卡语言或者OpenGL时的绘制,一切3D的物体我们都要自己动脑动手加上数 学运算进行绘制,这就增加了一些数学上的挑战。不过我认为,这对你来说应该不是问题,用Flash作3D图形一样会给你带来你意想不到的乐趣。那么开始 吧!

 

3D空间坐标系

从技术角度而言,Flash中并不存在3D,也就是说z轴并不存在,所以所谓的z轴是由你来制造的,也就是远景物体的大小。那么也就是说,对于一个 3D虚拟空间,z轴存在于当你看进显示器,x轴和y轴分别为横向和纵向。可是我们用什么方法来表达3D空间呢?我们需要两种手法来处理3D显示,缩放和层 叠。

 

 2D与3D坐标系

 

 

对于z轴的解释

在现实中,当一个物体离你远去,那么对你的眼睛来说,你所看到的是物体越来越小。当然并不只有物体的大小在改变,物体离你的距离也在增大。那么我们可以假定,在3D空间里,离得人眼越远的物体,它的大小就越小,那么它在x和y轴上的移动就越缓慢。很简单对吧?很好。

 

原点

Flash 中3D空间是围绕坐标系原点的,原点的坐标我们用Point(x, y, z), (0, 0, 0) 来表示。在Flash 2D中,原点存在于程序的左上角Point(0, 0),那么对于3D来说,原点也自然存在于程序的左上角,也许你会发现,如果原点在左上角的话,那么你所在的位置肯定是成一定角度来看程序中3D空间中的 物体的。当然我们可以把3D空间的原点向右再向下移动,那么我们在围绕原点绘制物体的时候会发现方便很多。

 

缩放物体

离人眼越近,那么物体就越大,反之物体就越小。物体缩放的比率以及移动速率与物体z的大小成反比。现在我用一个实例给你说明如何制造3D动画效果, 在这个例子中,我手工绘制了几个小球,作为我们关心的物体,让它们沿着z轴在舞台上来回移动,以制造3D效果。虽然很基本,不过别担心,把这些简单的东西 掌握好是深入探索的基础。

小球与3D空间(无层次)

 

动画制作步骤

1. 第一步,用Flash画出一个你喜欢的物体,任何物体都可以。在这个例子中我画了一个蓝色的小球。当然你可以导入你喜欢的图片,只不过不要忘记在 Library你创建的物体上点击右键,选择Linkage,然后在Export For Actionscript上打勾。

2. 下一步,详细解说一下代码。当然一开始我们要设置一些变量,原点和焦距(摄像机)。Focal length(焦距)确定了摄像机(在本例子中为人眼的)的凸透镜的焦距,值越大,那么物体的扭曲就会越小。我们把它设为300,这是一个在本例子中适中的数值。

var origin = new Object();
origin.x 
= stage.stageWidth/2;
origin.y 
= stage.stageHeight/280;

 

var focal_length = 400;

 

3. 创建一个舞台,并且把它的x和y设置为原点,这样我们在参照物体的时候就会非常简单易读了。

var scene = new Sprite();
this.addChild(scene);
scene.x 
= origin.x;
scene.y 
= origin.y;

 

4. 然后我们要在舞台上添加一些我们绘制好的小球。在这个例子中我们绘制3个,分别在左中右。把它们的x_3d, y_3d, z_3d,也就是他们的3D空间的x,y,z的值设为相应的数值,我把它们排为一排。给他们添加一个direction属性,1代表向屏幕方向移动,-1 代表向我们的方向移动。然后设置他们的移动速度,并且把它们添加到舞台上。这时你如果编译的话,你会看到有3个球在舞台上,那么下一步我们让它们运动起 来。

for (var i = 0; i < 3; i++)
{
    var sphere 
= new Sphere();
    sphere.x_3d 
= 190+i*160;
    sphere.y_3d 
= 80;
    sphere.z_3d 
= i*100;
    sphere.direction 
= 1;
    sphere.speed 
= 6;
    scene.addChild(sphere);
}

 

5. 下面这个函数,在每一次执行,都会把小球移动到相应的位置,并且对小球进行缩放。当小球的z大于600时,我们让它向相反的方向移动。当小球的z_3d值 变化后,我们计算小球当前的大小和位置,把小球移动到相应的位置然后对其进行缩放,这样在一连串的函数执行后,我们就会得到动画效果。

function run(e:Event)
{
    
for (var i = 0; i < scene.numChildren; i++)
    {
        scene.getChildAt(i).z_3d 
+= scene.getChildAt(i).speed*scene.getChildAt(i).direction;
        
if (scene.getChildAt(i).z_3d > 600)
        {
            scene.getChildAt(i).z_3d 
= 600;
            scene.getChildAt(i).direction 
= 1;
        }
        
else if (scene.getChildAt(i).z_3d < 0)
        {
            scene.getChildAt(i).z_3d 
= 0;
            scene.getChildAt(i).direction 
= 1;
        }
        
        var scale 
= focal_length/(focal_length+scene.getChildAt(i).z_3d);
        scene.getChildAt(i).x 
= scene.getChildAt(i).x_3d*scale;
        scene.getChildAt(i).y 
= scene.getChildAt(i).y_3d*scale;
        scene.getChildAt(i).scaleX 
= scene.getChildAt(i).scaleY = scale;
    }
}

 

6. 最后,在舞台上添加一个函数循环响应时间。让第5步我们写的函数循环执行。发布看一下,现在小球在3D舞台上移动了。

Hooray!你的第一个Flash3D程序完成了。总结一下,其实我们并没有使用任何高深的技巧,只不过是利用了变化物体的x和y以及小球的缩放来制造3D效果。

 

层叠

在Flash中表现3D空间,仅有缩放是不够的,我们还需要层叠。基本概念是,离人眼较近的物体会在离人眼较远的物体之上显示。
在上一节的例子里面,我们缩放小球,以达到3D效果。可是你会发现,3个小球之间的x距离都很大。你也许会想如果3个小球离得很近的话,会出现什么现象 呢?尝试把上面例子中小球之间的x距离变小,你会发现,不管小球离我们多远,右边的小球始终在最上面。即使中间的小球应该盖过右边小球的时候,右边的小球 还会在上面。这是因为在把小球添加到舞台上的时候,我们已经给了小球层次,也就是说最后添加的小球(右边的小球)就在最上面。

小球3D空间(无层次)间距太小啦!

我们应该设计一种方法实现小球的层次感,当小球离我们远的时候,那么它的层次就比较靠后,以此类推。换句话说,我们利用小球的z值给小球们分开层次,这也是我们即将要做的。在这个例子中,我们用7个小球的运动来说明是如何实现层次的。

小球3D空间(有层次)好多了!

 

动画制作步骤

1. 和上次的例子一样,重复6个步骤。不同的是我们初始化7个小球,并且把它们的x距离缩短。

for (var i = 0; i < 7; i++)
{
    var sphere 
= new Sphere();
    sphere.x_3d 
= 150+i*40;
    sphere.y_3d 
= 80;
    sphere.z_3d 
= Math.random()*(0600)+600;
    sphere.direction 
= 1;
    sphere.speed 
= Math.random()*(512)+12;    
    scene.addChild(sphere);
}

 

2. 利用Bubble Sort算法,在每一次对小球x,y和大小设置后,对所有的小球在舞台上的层次进行操作。这里使用的理论是最小的z值的小球,它所在层次就应该在最上面。

function swap_depth(container:Sprite)
{
    
for (var i = 0; i < container.numChildren  1; i++)
    {
        
for (var j = container.numChildren  1; j > 0; j)
        {
            
if (Object(container.getChildAt(j1)).z_3d < Object(container.getChildAt(j)).z_3d)
            {
                container.swapChildren(container.getChildAt(j
1), container.getChildAt(j));
            }
        }
    }
}

 

3. 然后在循环函数里的最后加上

swap_depth(scene);

 

本文章旨在讨论如何在Flash中实现3D动画,对于一些算法,比如这一节中使用到的冒泡排序算法,我就不再多说了。当然你可以选择使用插入排序 (可能运算起来比较快40%?!)。你可以完全拷贝我写的代码去使用,但是请务必注明出处。如果是排序的话,google或者百度一下,我相信你会找到更 详细的说明文字来解释冒泡排序。

OK,你已经学会了如果使用缩放和一些简单的设置产生3D效果的动画。在后面的几篇中,我们会逐渐深入探讨更有趣的内容。加油!

 

点此下载本节源文件


作者:Yang Zhou
出处:http://yangzhou1030.cnblogs.com
感谢:Yunqing
本文版权归作者和博客园共有,转载未经作者同意必须保留此段声明。请在文章页面明显位置给出原文连接,作者保留追究法律责任的权利。

[Flash]Flash3D编程探秘二

mikel阅读(807)

作者:Yang Zhou
感谢:Crystal

介绍

对 学习Flash中的3D编程感兴趣?那么你来对地方了。在这篇文章中,我将陆续的介绍在Flash中使用Actionsript进行3D编程一些实例。这 是一篇初级到中级难度的学习资料,如果你具有一些基本的几何知识,那对你来说不会太难。虽然例子中运用了非常简单的程序构架和实现方法,但是我还是期望你 已经有大量的Actionscirpt和Flash经验,这样你在使用以及理解Actionscript语言的时候不会有太大的障碍。如果你在阅读中发现 很多地方不清楚,或者这些对你来说是比较新的东西,那么我建议你参考我写过的另外几篇3D的基础知识的文章。

文章中含有大量的代码和一些算法的实现,在这里你可以完全拷贝我写的代码去使用,但是请务必注明出处。

 

点此下载本节源文件

 

静态长方体

那么我们接着上一节所学习的内容,来制作一个静态的长方体,并且让它在屏幕上来回的运动。这个例子和上一节的例子非常的相似,同样主要关心3D空 间。不同的是,上一节我们利用了一个事先画好的小球,这一节我们改变方式,在程序执行时,我们计算出长方体的每个顶点的位置然后使用Flash的图形 API绘制出一个长方体,这样在一系列的绘制后,我们所看到的就是长方体移动的动画!

移动的静态长方体

 

动画制作步骤

1. 在这一个例子中,我们需要发挥一下我们的空间想象力去定位长方体的顶点。至于场景上的网格,我想大家可以先把它放在场景的底部,等动画完成后再把它向上移动到合适的位置。

2. 开始和以前一样,定义原点以及焦距。另外我们也要初始几个常量。长方体围绕y轴公转,R是长方体公转的半径。

var PI = 3.1415926535897932384626433832795;

var R = 100;

var origin = new Object();
origin.x 
= stage.stageWidth/2;
origin.y 
= stage.stageHeight/2;
origin.z 
= 0;

var focal_length = 300;
var angular_Velocity = PI/160;
var _angle_xz = 0;

 

3. 接下来定义一个3D空间的点,我们绘制的长方体就围绕这个点进行旋转。

var spin_center = new Object();
spin_center.x 
= 0;
spin_center.y 
= 0;
spin_center.z 
= 100;

 

4. 创建一个场景舞台,用来盛放我们绘制的长方体。创建一个长方体的空Sprite并且把它添加到舞台上。

var scene = new Sprite();
scene.x 
= origin.x;
scene.y 
= origin.y
this.addChild(scene);
var box:Sprite 
= new Sprite();
scene.addChild(box);

 

5. 下面我们需要一个函数来创建3D空间的点。

function vertex(x, y, z):Object
{
    var point3d 
= new Object();
    point3d.x 
= x;
    point3d.y 
= y;
    point3d.z 
= z;
    
return point3d;
}

 

6. 你肯定猜到下一步我们要做的,那就是把一个3D空间的点转换成Flash能够理解的2D空间的点。转换的原理和第一节是一样的,这里就不解释了。

function convert(point3d, focal_length):Object
{
    var point2d 
= new Object();
    var scale_ratio 
= focal_length/(focal_length+point3d.z);
    point2d.x 
= point3d.x * scale_ratio;
    point2d.y 
= point3d.y * scale_ratio;
    
return point2d;
}

 

7. 下一步也就是我们主要关心的循环函数。首先我想你明确这个函数要做的工作,那就是计算出长方体每个顶点的3D坐标,然后把他们转化成2D坐标,最后用 Flash的绘制API建立图形。每一次函数执行,我们把长方体围绕y轴旋转的角度增加。(当然这里你可以长方体的运动改为以时间为依据的运动)然后根据 这个角度,我们便可以计算出长方体中心点(对角线的交点)cente.x,center.y,center.z。很好,下面我们就可以确定这个长方体的每 个点的坐标了。在这里我使用了一个边长为80正方体,你可以更改参数调试出你喜欢的长方体。

 

俯瞰长方体的移动

 

 

那么紧接着,使用我们之前写的函数,把长方体的6个3D顶点转换成2D点。然后用Flash的绘制函数绘制出来长方体。需要注意的是,我们在这里是对空间中的点进行操作而不是对一个Sprite进行操作。

function move(e:Event):void
{
    var screen_points 
= new Array();
    
    _angle_xz 
+= angular_Velocity;
    
if (_angle_xz > 360)
    {
        _angle_xz 
-= 360;
    }
    var center 
= new Object();
    center.x 
= R*Math.cos(_angle_xz) + spin_center.x;
    center.y 
= 0 + spin_center.y;
    center.z 
= R*Math.sin(_angle_xz) + spin_center.z;
    
    var points 
= [
            vertex(center.x
4040, center.z40),    
            vertex(center.x
+4040, center.z40),        
            vertex(center.x
+4040, center.z+40),
            vertex(center.x
4040, center.z+40),
                    
            vertex(center.x
4040, center.z40),
            vertex(center.x
+4040, center.z40),
            vertex(center.x
+4040, center.z+40),
            vertex(center.x
4040, center.z+40)
             ];
    
for (var i = 0; i < points.length; i++)
    {
        screen_points[i] 
= convert(points[i], focal_length);
    }
    
    with (box.graphics)
    {
        clear();
        lineStyle(.
50x0000001);
        moveTo(screen_points[
0].x, screen_points[0].y);    
        lineTo(screen_points[
1].x, screen_points[1].y);
        lineTo(screen_points[
2].x, screen_points[2].y);
        lineTo(screen_points[
3].x, screen_points[3].y);
        lineTo(screen_points[
0].x, screen_points[0].y);
        
        moveTo(screen_points[
4].x, screen_points[4].y);    
         lineTo(screen_points[
5].x, screen_points[5].y);
        lineTo(screen_points[
6].x, screen_points[6].y);
        lineTo(screen_points[
7].x, screen_points[7].y);
        lineTo(screen_points[
4].x, screen_points[4].y);
        
        moveTo(screen_points[
0].x, screen_points[0].y);    
        lineTo(screen_points[
4].x, screen_points[4].y);
        moveTo(screen_points[
1].x, screen_points[1].y);
        lineTo(screen_points[
5].x, screen_points[5].y);
        moveTo(screen_points[
2].x, screen_points[2].y);
        lineTo(screen_points[
6].x, screen_points[6].y);
        moveTo(screen_points[
3].x, screen_points[3].y);
        lineTo(screen_points[
7].x, screen_points[7].y);
    }
}

 

8. 最后在场景上添加一个循环执行事件。

this.addEventListener(Event.ENTER_FRAME, move);

 

我希望你能够明确我们制作这个动画的思路:建立场景,创建3D物体,把顶点转换成为2D点,使用Flash绘制。So far so good? Great! 后面我们开始介绍摄像机以及相关的要素,希望你能跟上。

建议:

在你的脑海中建立一个长方体应该不是很困难。我的方法是首先勾勒出正面,然后后面,上面,下面,左面和右面。如果你觉得用脑海想象比较困难的话,可以试着用笔和纸画出一个长方体,然后标出坐标。

建议:

在Flash里,2D空间的原点在左上角(0,0)。在这上面的两节的例子中,我们在程序一开始就把3D空间的原点向右再向下移动了,那么在屏幕上的映射 面也就到了屏幕的中间。我是刻意这样写的,好处在于如果你是新接触3D空间这个课题的话,那么想象物体在原点附近对你来说要容易一些。当然你可以尝试不移 动原点,取而代之移动物体,看看和原程序有什么不同。

作者:Yang Zhou
出处:http://yangzhou1030.cnblogs.com
感谢:Yunqing
本文版权归作者和博客园共有,转载未经作者同意必须保留此段声明。请在文章页面明显位置给出原文连接,作者保留追究法律责任的权利。

[Flash]Sandy 3D

mikel阅读(966)

Sandy

Sandy is an intuitive and user-friendly 3D open-source library developed in Actionscript 2 and now Actionscript 3 for the Flash environment.

This project is updated very often, and the latest release is the 3.0.2 official release. The latest version is available on the website : flashsandy.org

Some technical demos (get all of them there: http://www.flashsandy.org/demos/ )

walker.jpg

flightsim.jpg

You can download the latest version here : http://www.flashsandy.org/download

New 3.0 release features

Here a list of main features:

  • Simple and more powerful API
  • Frustum culling and Frustum clipping
  • compatible with majority of tween libraries (Tweener, etc. )
  • real scene graph representation, with a fully integration of the camera as an element of this scene tree.
  • flexible skinning of objects. Each material has some attributes that allow it display more information (edges, outine, light)
  • Parsers able to load more that 1 single object. (ASE, 3DS-basic-, COLLADA formats)
  • possibility to choose the depth sorting between Object and Polygon level.
  • built-in bubbling event system
  • Sprite2D and Sprite3D (understand oriented sprite) integration.

Characteristics

This 3D engine features many exclusive characteristics such as :

  • Flash player 7 compatibility.
  • Both MTASC and Macromedia compilers compliant.
  • Several 3D primitives, allowing fast and parameterized object creation
  • Advanced object management allowing some fantastic possibilities during your creations (scaling, rotation, translation, etc.)
  • API based on Java3D, the reference open-source Java 3D API
  • Advanced camera management (multiple cameras, rotation, motion on linear or bezier-curve path, movements, etc.)
  • Complex object loading thanks to the .ASE and .WRL files parser (files generated by several 3D object modeling packages such as 3D Studio Max)
  • Skin system to easily change your objects appearance. Several skins are available allowing to create transparent faces, bitmap texture and video texture as webcam video stream.
  • Managment of Flash8 filters bringing some very nice visual effects

Why this project ?

The idea comes from the lack of possibilities to run 3D in Flash. This project goals are to supply the more reliable and flexible API to users, plus reach the highest performance level possible.

Author

Thomas Pfeiffer started this project in Oct 2005 and since, a small but complete team has been created: Development team

Some people have kindly contributed to the project, and you can see the list here: contributors

Why this name ?

Sandy is intended to be a community project, with a simple API, documented and updated as much as possible. Sandy is a pun which represents 3D. I’ve been inspired by the Chinese language because ‘3’ is pronounced ‘san’ and the letter ‘D’ ‘di’. Combining those two words I got sandy.

[FCKEditor]使用FCKeditor_2.6.3版本有关上传图片问题解决

mikel阅读(923)

使FCKeditor_2.6.3版本有关上传图片问题解决

问题:提示This connector is disabled

解决:
在fckeditor\editor\filemanager\connectors\aspx目录下面有一个 config.ascx 用户控件。打开它,我们可以看到有一个:private bool CheckAuthentication()的方法。
private bool CheckAuthentication()
 {
  // WARNING : DO NOT simply return "true". By doing so, you are allowing
  // "anyone" to upload and list the files in your server. You must implement
  // some kind of session validation here. Even something very simple as…
  //
  //  return ( Session[ "IsAuthorized" ] != null && (bool)Session[ "IsAuthorized" ] == true );
  //
  // … where Session[ "IsAuthorized" ] is set to "true" as soon as the
  // user logs in your system.
 
  return false;
  }
默认是返回false的,返回true就可以了。不要轻易的返回true,要不然任何人都可以上传文件到你的服务器。可以在这里验证session的值来判断用户是否可以上传文件。
 

问题:FCKEditor 图片上传一直显示进度条的问题


解决:

很多博主介绍配置FCKeditor的目录时都是这样写的,我不知道是不是大家互相复制的关系

<appSettings>
    <add key="FCKeditor:BasePath" value="~/FCKeditor/"/>
    <!–FCKeditor基本文件目录–>
    <add key="FCKeditor:UserFilesPath" value="/UserFiles/"/>
    <!–文件上传目录–>
  </appSettings>

大家看一下上面两个配置有什么区别没有,"~/FCKeditor/"比"/UserFiles/"前面多了符号“~”。

在“/UserFiles/”前面加上“~”符号就可以了。

这个错误还会导致下面的问题:在单击浏览服务器按钮是提示:未能映射路径“/Files/image/”,具体提示如下:

==========================================================================================

—————————
Microsoft Internet Explorer
—————————
The server didn't send back a proper XML response. Please contact your system administrator.

XML request error: Internal Server Error (500)

Requested URL:
http://localhost:7958/FCKeditorTest/FCKeditor/editor/filemanager/connectors/aspx/connector.aspx?Command=GetFoldersAndFiles&Type=Image&CurrentFolder=%2F&uuid=1224920141937

Response text:
<html>

    <head>

        <title>未能映射路径“/UserFiles/image/”。</title>

        <style>

         body {font-family:"Verdana";font-weight:normal;font-size: .7em;color:black;}

         p {font-family:"Verdana";font-weight:normal;color:black;margin-top: -5px}

         b {font-family:"Verdana";font-weight:bold;color:black;margin-top: -5px}

         H1 { font-family:"Verdana";font-weight:normal;font-size:18pt;color:red }

         H2 { font-family:"Verdana";font-weight:normal;font-size:14pt;color:maroon }

         pre {font-family:"Lucida Console";font-size: .9em}

         .marker {font-weight: bold; color: black;text-decoration: none;}

         .version {color: gray;}

         .error {margin-bottom: 10px;}

         .expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }

        </style>

    </head>

 

    <body bgcolor="white">

 

            <span><H1>“/FCKeditorTest”应用程序中的服务器错误。<hr width=100% size=1 color=silver></H1>

 

            <h2> <i>未能映射路径“/UserFiles/image/”。</i> </h2></span>

 

            <font face="Arial, Helvetica, Geneva, SunSans-Regular, sans-serif ">

 

            <b> 说明: </b>执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。

 

            <br><br>

 

            <b> 异常详细信息: </b>System.InvalidOperationException: 未能映射路径“/UserFiles/image/”。<br><br>

 

            <b>源错误:</b> <br><br>

 

            <table width=100% bgcolor="#ffffcc">

               <tr>

                  <td>

                      <code>

 

执行当前 Web 请求期间生成了未处理的异常。可以使用下面的异常堆栈跟踪信息确定有关异常原因和发生位置的信息。</code>

 

                  </td>

               </tr>

            </table>

 

            <br>

 

            <b>堆栈跟踪:</b> <br><br>

 

            <table width=100% bgcolor="#ffffcc">

               <tr>

                  <td>

                      <code><pre>

 

[InvalidOperationException: 未能映射路径“/UserFiles/image/”。]

   System.Web.Hosting.HostingEnvironment.MapPathActual(VirtualPath virtualPath, Boolean permitNull) +615

   System.Web.VirtualPath.MapPathInternal() +29

   System.Web.HttpRequest.MapPath(VirtualPath virtualPath, VirtualPath baseVirtualDir, Boolean allowCrossAppMapping) +125

   System.Web.HttpServerUtility.MapPath(String path) +58

   FredCK.FCKeditorV2.FileBrowser.TypeConfig.GetFilesDirectory() +63

   FredCK.FCKeditorV2.FileBrowser.FileWorkerBase.ServerMapFolder(String resourceType, String folderPath, Boolean isQuickUpload) +37

   FredCK.FCKeditorV2.FileBrowser.Connector.GetFolders(XmlNode connectorNode, String resourceType, String currentFolder) +21

   FredCK.FCKeditorV2.FileBrowser.Connector.OnLoad(EventArgs e) +708

   System.Web.UI.Control.LoadRecursive() +49

   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3743

</pre></code>

 

                  </td>

               </tr>

            </table>

 

            <br>

 

            <hr width=100% size=1 color=silver>

 

            <b>版本信息:</b>&nbsp;Microsoft .NET Framework 版本:2.0.50727.42; ASP.NET 版本:2.0.50727.42

 

            </font>

 

    </body>

</html>

<!–

[InvalidOperationException]: 未能映射路径“/UserFiles/image/”。

   在 System.Web.Hosting.HostingEnvironment.MapPathActual(VirtualPath virtualPath, Boolean permitNull)

   在 System.Web.VirtualPath.MapPathInternal()

   在 System.Web.HttpRequest.MapPath(VirtualPath virtualPath, VirtualPath baseVirtualDir, Boolean allowCrossAppMapping)

   在 System.Web.HttpServerUtility.MapPath(String path)

   在 FredCK.FCKeditorV2.FileBrowser.TypeConfig.GetFilesDirectory()

   在 FredCK.FCKeditorV2.FileBrowser.FileWorkerBase.ServerMapFolder(String resourceType, String folderPath, Boolean isQuickUpload)

   在 FredCK.FCKeditorV2.FileBrowser.Connector.GetFolders(XmlNode connectorNode, String resourceType, String currentFolder)

   在 FredCK.FCKeditorV2.FileBrowser.Connector.OnLoad(EventArgs e)

   在 System.Web.UI.Control.LoadRecursive()

   在 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

[HttpUnhandledException]: 引发类型为“System.Web.HttpUnhandledException”的异常。

   在 System.Web.UI.Page.HandleError(Exception e)

   在 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

   在 System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

   在 System.Web.UI.Page.ProcessRequest()

   在 System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)

   在 System.Web.UI.Page.ProcessRequest(HttpContext context)

   在 ASP.fckeditor_editor_filemanager_connectors_aspx_connector_aspx.ProcessRequest(HttpContext context)

   在 System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()

   在 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

–>
—————————
确定  
—————————

============================================================================================================

以上问题都是根据测试推断出的,我并不知道源码是怎么处理的,希望高手能给予指点。

相关链接:

FCKeditor_2.6.3的安装使用方法

[C#]WebService序列化

mikel阅读(1210)

 1 /// <summary>
 2     /// 序列化DataTable
 3     /// </summary>
 4     /// <param name="pDt">包含数据的DataTable</param>
 5     /// <returns>序列化的DataTable</returns>
 6     private static string SerializeDataTableXml(DataTable pDt) {
 7         // 序列化DataTable
 8         StringBuilder sb = new StringBuilder();
 9         XmlWriter writer = XmlWriter.Create(sb);
10         XmlSerializer serializer = new XmlSerializer(typeof(DataTable));
11         serializer.Serialize(writer, pDt);
12         writer.Close();
13 
14         return sb.ToString();
15     }
16 

 1 /// <summary>
 2         /// 反序列化DataTable
 3         /// </summary>
 4         /// <param name="pXml">序列化的DataTable</param>
 5         /// <returns>DataTable</returns>
 6         public static DataTable DeserializeDataTable(string pXml) {
 7 
 8             StringReader strReader = new StringReader(pXml);
 9             XmlReader xmlReader = XmlReader.Create(strReader);
10             XmlSerializer serializer = new XmlSerializer(typeof(DataTable));
11 
12             DataTable dt = serializer.Deserialize(xmlReader) as DataTable;
13 
14             return dt;
15         }
16