[转载]工作多年的.NET程序员,是否建立了自己的开发知识库?分享制作电子书的经验

mikel阅读(838)

[转载]工作多年的.NET程序员,是否建立了自己的开发知识库?分享制作电子书的经验 – James Li – 博客园.

经过多年的编程经验的积累,工作中肯定会遇到很多问题,也都通过各种办法解决了。无论是 上网搜索,或是向同事寻求帮忙,在遇到问题时,都会把这个系列的问题的网页都保存起来,以便以后查找起来方便。这样,随着时间的积累,知识库的内容会越来 越多,如何整理这些文件,方便查找,一直是工作之外努力的方向。

曾经用EverNote建立各种知识库,如下图所示,定期抽出时间,在网上搜索,看到好的文章,都剪贴下来

image

几个月下来,就积累了几十兆的数据,大部分是含有简单格式的文本数据,可设置格式,打印,非常方便。而且EverNote这个软件是绿色版,一共才8M多。每次要重装系统或是搬动数据资料,也连同软件一起拷贝。

与 EverNote同名的是微软的OneNote,一直不喜欢微软的捆绑风格,为了记个笔记,搜集点资料,要装那么大的软件,而且有时候会安装不成功,文件 组织方式也不同于EverNote,EverNote会按照数据库来组织你的笔记内容,你可以把相关的知识内容都放到一个数据库中,OneNote是按照 文件名来组织笔记,相比两者,更喜欢EverNote的风格。

更多的时候,忙于工作,没有时间上网,一直等到空闲的时候,想找个安静的地方学习(图书馆),又没有条件上网,如果你面对这样的情况,推荐下面这种方式给你,依照这个步骤,可以让你达到同样的效果。

1 下载网页文件到本机磁盘中

image

Data Loader是我为了搜集资料而开发的一个软件,如图所示。文本编辑器中是博客园中排名靠前的博主,他们的文章质量高,读起来效果好,项目忙,工作忙,常 常没有时间去一页页的读,然后拷贝到WORD,于是就想到用这个软件,分门别类,把他们的文章,都下载到本机磁盘中。点击Start按钮后,后台程序会下 载他们的文章到本地磁盘的G:\Document中。

image

所采用的格式是mht格式,可以保存图片,mht也是邮件的格式。如果可能,也可以通过互操作类型,把它存成DOC/DOCX格式,PDF格式也行,做这件事,对于程序员来说,不难。

2  Power CHM 登场,制作成CHM格式

博客园中Foundation博主写的工作流系列非常精彩,我用Power CHM导入上图中的目录,效果如下

image

这些是简单的活,不需要复杂的技术,点击File->Import Directory即可。可能有的页面会报脚本错误,没有关系,先不管,到后面再编辑它。点击Tools->CHM Compile ,生成CHM文件。
Power CHM已经内置了编译CHM文件的类型库,不需要安装Help workshop。顺便来看一下它的文件结构,我对这个hh.exe,hha.ddl感觉特别亲切,因为自己也曾经调用它来生成CHM文件,只是没有想到 做得更好,做成像Power CHM这样优秀的软件。这使我想到,做技术的致命缺点,懂一点,但又懂得不精,没有深入的研究,浅尝辙止。

image

等待一段时间,喝杯茶提提神,或是吃个苹果,片刻之后,就可以看到产生出的CHM文件了,如下图所示

image

我们就轻松的获取了CHM格式的电子书。依照这个办法,你可以做很多电子书。

在 我的Data Loader开放下载之前,你可以使用其他的网页下载软件,把网页下载到本地。实在找不到,写一个,调用WebClient类型,也应该是个把钟头的事 情,不会太难。先不要考虑太多问题,比如多线程,比如异步,你只是需要一个小程序来帮忙你把指定的网页下载到本地,记住,先把问题简化,有助于达到最终的 目的。

3  编辑CHM文件 整理成精致的CHM电子书

每位开发人员对技术的定位点不同,不同的开发阶段有不同的知识需求,这样,需要对CHM文件的内容进行取舍,制作需要的电子书。启动CHM Editor,打开刚才生成的Foundation.chm文件,如下图所示

image

CHM Editor专门用来编辑CHM文件,可对它直接进行编辑,即时保存。把不需要的文章删除,不需要的部分去掉,保存之后,就是我们需要的专题电子书了。此外,CHM Editor也是制作CHM文件的好工具,有了这个工具,你可以忽视网页

的存在。直接编辑,即时保存,就是你所需要的电子书文件。

CHM 格式仍然是Windows平台上流行的电子书格式文件,EXE格式容易被报病毒,或是被感染,PDF的格式查找不方便,缺少了CHM文件左边的树型导航 (虽然可以做出书签来,但是大量的免费的书都没有书签,自己做又很麻烦),会逊色很多。不过PDF着重点在于可移植的文档格式,是通用的格式,而CHM只 适用于Windows平台。

[转载]使用Windbg知道程序运行时的命令行参数.

mikel阅读(1083)

[转载]使用Windbg知道程序运行时的命令行参数. – 嗷嗷 – 博客园.

如何才能一个程序运行时的command line arguments是什么?其实这个信息被记录在了进程的process environment block中,我们可以用Windbg很方便的找出这个信息。

比如说,我在cmd上打开一个notepad, 如下

clip_image001

当notepad运行起来以后,使用windbg attach到notepad, 然后使用命令!peb打印出process environment block. 要注意symbol path要正确。

然后就能看到下面这些信息了。

clip_image002

我们能知道CommandLine了,也能知道DllPath和Environment了.

那么有时候这个程序运行的太快了,还来不及attach就跑完了怎么办?

没关系,我们可以设置notepad.exe一运行就被windbg断下来。这要用到windbg下的另外一个非常有用的工具了,gflags.exe. 按如下图设置notepad.exe

clip_image003

其效果是在注册表中添加了下面一些信息:

clip_image004

现在只要notepad以运行,首先就会被windbg断下来了。

总结,其实也不一定使用Windbg,使用VS的Debugger也是可以的,原理一样,就不详述了。

另外,使用Process Monitor来得到程序运行参数更方便

最后嘛,惯例是要配图的。不过最近手上没有好图,下次吧。

[转载]FLEX+Webservice 大附件上传、断点续传实现

mikel阅读(1175)

转载FLEX+Webservice 大附件上传、断点续传实现 – 大侠酷裤马路 – 博客园.

最近项目需要,面临大附件上传的功能,具体研究如下:
实现思路
大附件上传,如何流畅不占用内存,还要支持断点续传,当第一次看到这 些需求的时候还是有所顾虑,传统ASP.NET中利用fileupload可以实现上传,但是webconfig中文件大小受限制,即使设置大小了也将面 临超时的问题。对于上述情况,WINFORM应该能够很好的解决断点续传大文件,当应用到WEB应用中的时候就很难如此轻松了,因此富客户端思想是很好的 选择,决定采用FLEX实现客户端,Webservice实现客户端。
由于ASP.NET默认支持4M大小文件上传,一次需要将需要上传的文件进行分割,客户端分块上传,服务端分块追加。
具体实现
1)、客户端实现

客户端界面设计

<s:Group width=”100%” height=”100%”>
<s:Button id=”btnBrower” x=”390″ y=”25″ label=”浏览…” width=”60″ click=”btnBrower_clickHandler(event)”></s:Button>
<s:TextInput id=”edFile” x=”21″ y=”24″ width=”361″ enabled=”false”/>
<s:Button id=”btnUpload” x=”458″ y=”25″ label=”开始上传” width=”71″ click=”btnUpload_clickHandler(event)”/>
<mx:Canvas width=”508″ height=”25″ backgroundColor=”0Xf1f1f1″ x=”21″ y=”53″ borderStyle=”solid” borderColor=”0Xbbbbbb”>
<mx:Label text=”” fontWeight=”bold” id=”tip_txt” x=”5″ y=”4″/>
</mx:Canvas>
<mx:Canvas id=”totalProcess” borderStyle=”solid” x=”22″ width=”507″ y=”82″ height=”13″ borderColor=”0X124fc0″ backgroundColor=”0xffffff”>
<mx:Canvas backgroundColor=”0X124fc0″ backgroundAlpha=”0.5″ id=”processBar_Total” width=”0″ height=”23″/>
</mx:Canvas>

</s:Group>

定义Webservice方法,对应服务端,各自有自己的返回事件

<s:WebService id=service wsdl=../Service.asmx?wsdl useProxy=false>
<s:operation name=WriteFile result=onResult(event) fault=onFault(event)>
</s:operation>
<s:operation name=CheckFile result=onCheckResult(event) fault=onCheckFault(event)>
</s:operation>
<s:operation name=CopyFile result=onCopyResult(event) fault=onCopyFault(event)>
</s:operation>
</s:WebService>

浏览需要上传的文件

//页面加载完毕,进行相关事件注册
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
// 注册调用js函数
ExternalInterface.addCallback(getFileInfo,GetFileInfo);

//初始化文件浏览事件
file.addEventListener(Event.SELECT,onSelect);//选择文件事件
file.addEventListener(Event.COMPLETE,onComplete);//文件加载完毕
file.addEventListener(Event.OPEN,onOpen);
btnUpload.enabled
=false;
}

//浏览文件
private function onSelect(evt:Event):void
{
this.tip_txt.text=“”;
edFile.text
=file.name;
//浏览完成,开始加载
file.load();
}
//加载文件完毕
private function onComplete(evt:Event):void
{
this.tip_txt.text=加载完毕;
btnUpload.enabled
=true;
}

private function onOpen(evt:Event):void
{
this.tip_txt.text=正在加载…;
}

校验服务端文件是否存在,不存在则创建,存在则判断是否需要断点续传

//校验文件函数
private function CheckFile():void
{
//调用webservice方法,传递文件名进行校验
service.CheckFile.send(file.name);
}
//webervice,校验成功
private function onCheckResult(event:ResultEvent):void
{
//获取返回值
var retArray:Array=new Array();
retArray
=event.result.toString().split(,);
var retMsg:String=retArray[0].toString();//返回文件存在与否消息
var retNum:int=int(retArray[1].toString());//返回文件大小
tip_txt.text=retMsg;

//判断是否存在文件
if(retNum != 0)
{
//若文件已经存在,判断文件是否已经上传完毕
if(retNum == file.data.length)
tip_txt.text
=文件已上传完毕;
else
{
tip_txt.text
=准备断点续传;

//断点续传需要重新计算块数,剩余大小
var Leave:int= file.data.lengthretNum;

//判断剩余情况
if(Leave>blocksize)
{
//剩余部分分块
var BlockNum2:Number=(Leave / blocksize);
BlockNum
=int(BlockNum2);
BlockNumles
=int(BlockNum2);
reBlock
=Leave % blocksize;
tip_txt.text
=正在处理…;
//调用上传函数
uploadFile(retNum,blocksize);
}
else
{
//直接从返回值大小开始,传递剩余部分
BlockNumles=1;
uploadFile(retNum,reBlock);
}
}
}
else
{
//若文件不存在,则创建,从0开始
var BlockNum1:Number=(file.data.length / blocksize);
BlockNum
=int(BlockNum1);
BlockNumles
=int(BlockNum1);
reBlock
=file.data.length % blocksize;

tip_txt.text=正在处理…;
uploadFile(retNum,blocksize);
}
}

private function onCheckFault(event:FaultEvent):void
{
Alert.show(event.toString());
}

开始上传

//上传附件函数
private function uploadFile(begin:int,end:int):void
{
//判断文件大小
if(file.data.length>blocksize)
{
//读取部分文件,分块上传
fileUpload.writeBytes(file.data,begin,end);
service.WriteFile.send(file.name,fileUpload);
}
else
{
//直接上传
service.WriteFile.send(file.name,fileUpload);
}
}

//webservice相关事件函数,上传成功
private function onResult(event:ResultEvent):void
{
//每次上传成功返回值,作为下次传递的开始位置
var begin:int=int(event.result.toString());
BlockNumles
-=1;//递减
BlockNumadd+=1;//递增
//清空历史数据
fileUpload.clear();

//进度条
onProgress(begin,file.data.length);
//判断剩余块多少,进行不同情况的上传
if(BlockNumles>0)
{
uploadFile(begin,blocksize);
}

if(BlockNumles==0)
{
uploadFile(begin,file.data.length
begin);
tip_txt.text
=上传完毕!;
tip_txt.text
=开始扫描文件…;
service.CopyFile.send(file.name);
}
}
//上传失败
private function onFault(event:FaultEvent):void
{
Alert.show(
event.toString());
}

进度监视

//上传进度条
private function onProgress(Loaded:int,Total:int):void
{
processBar_Total.width
=(Loaded/Total)*506;
tip_txt.text
=已上传: + Loaded+/+Total;
if(Loaded==Total)
tip_txt.text
=已上传完毕;
}

上传完毕处理文件,完毕之后需要对文件进行类似处理,在这里是对文件进行重命名。具体在客户端可以体现出来

//复制文件
private function onCopyResult(event:ResultEvent):void
{
tip_txt.text
=扫描完成;
//文件上传结束,调用js函数
var f:String = showButton;
var m:String
= ExternalInterface.call(f);
trace(m);
}

private function onCopyFault(event:FaultEvent):void
{
Alert.show(
event.toString());
}

2)、服务端实现
对应客户端三个方法实现,分别是校验、上传、上传完毕
校验文件,并返回值

#region 校验文件是否存在
[WebMethod]
public string CheckFile(string FileName)
{
string FileSavePath = Server.MapPath(File/) + FileName;
if (!IsExistFile(FileSavePath))
return 文件不存在,0;
else
{
string FileSize = GetFileSize(FileSavePath).ToString();
return 文件已存在, + FileSize;
}
}
#endregion

开始写文件,没有则创建,有则追加

#region 写文件
[WebMethod]
public string WriteFile(string FileName, byte[] filestrem)
{
string FileSavePath = Server.MapPath(File/) + FileName + .temp;
if (!IsExistFile(FileSavePath))
{
FileStream fs
= new FileStream(FileSavePath, FileMode.Create);
//获得字节数组
byte[] data = filestrem;
//开始写入
fs.Write(data, 0, data.Length);
//清空缓冲区、关闭流
fs.Flush();
fs.Close();
}
else
{
//追加文件
using (System.IO.FileStream f = new System.IO.FileStream(FileSavePath, System.IO.FileMode.Append, FileAccess.Write))
{
byte[] b = filestrem;
f.Write(b,
0, b.Length);
}
}

return GetFileSize(FileSavePath).ToString();
}
#endregion

上传完毕

#region
[WebMethod]
public string CopyFile(string FileName)
{
string FileSavePath = Server.MapPath(File/) + FileName+.temp;
string FileConvertPath = Server.MapPath(ConvertFile/) + FileName;

//如果目标中存在同名文件,则删除
if (IsExistFile(FileConvertPath))
{
DeleteFile(FileConvertPath);
}
//将文件复制到指定目录
File.Copy(FileSavePath, FileConvertPath);

//删除原始临时文件
DeleteFile(FileSavePath);

string Path = FileConvertPath;
return Path;
}
#endregion

存在问题
客户端要把文件读取完毕之后,才开始分段上传,如果文件过大,内存玩儿不转那么浏览器将会死掉。需要继续改进,请大家拍 砖!!源代码全部奉上,了解flex的可以看看flex部分源码,不了解的可以直接在项目中使用,已经在.NET项目中配置完毕,可直接运行看到效果。本 例子仅为beta1.0版本,还在继续修改当中。

效果图:

源码:断点续传.rar

[转载]漂亮的后台WebUi框架(有源码下载)

mikel阅读(935)

[转载]漂亮的后台WebUi框架(有源码下载) – 孟晨 – 博客园.

今天分享下以前收藏的几个漂亮的后台WebUi框架,之前听人说到“一个项目最重要的是前台,后台谁看啊”,这话说的,是,领导是只看前台界面,但系统 管理员呢?不能不说前台不重要,前台是很重要,但后台怎么能不重要呢,大部分数据要靠后台来输入,操作。如果一个好的后台界面,漂亮的,易用的页面对系统 来说也很重要,如果你是系统管理员看到一个很草的后台,也会不爽吧,今天就给大家分享几套不错的后台框架,有源码下载。


打包下载,可用的模板

[转载]Android定位功能(一)

mikel阅读(861)

[转载]Android定位功能(一) – 熊猫82 – 博客园.

废话不多说,直接开始说说与实现Android定位有关的API吧。

这些API都在Android.location包下,一共有三个接口和八个类。它们配合使用即可实现定位功能。

三个接口:

GpsStatus.Listener: 这是一个当GPS状态发生改变时,用来接收通知的接口。

GpsStatus.NmeaListener: 这是一个用来从GPS里接收Nmea-0183(为海用电子设备制定的标准格式)信息的接口。

LocationListener: 位置监听器,用于接收当位置信息发生改变时从LocationManager接收通知的接口。

八个类:

Address: 描述地址的类,比如:北京天安门

Criteria: 用于描述Location Provider标准的类,标准包括位置精度水平,电量消耗水平,是否获取海拔、方位信息,是否允许接收付费服务。

GeoCoder: 用于处理地理位置的编码。

GpsSatellite: 和GpsStatus联合使用,用于描述当前GPS卫星的状态。

GpsStatus: 和GpsStatus.Listener联合使用,用于描述当前GPS卫星的状态。

Location: 用于描述位置信息。

LocationManager: 通过此类获取和调用系统位置服务

LocationProvider: 用于描述Location Provider的抽象超类,一个LocationProvider应该能够周期性的报告当前设备的位置信息。

这里通过一个代码示例,演示一下如何实现定位。

首先,在AndroidManifest.xml清单文件里需要加入ACCESS_FINE_LOCATION权限

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>

其次,实现代码如下:

 package com.test;
 import java.io.IOException;
 import java.util.List;

 import android.app.Activity;
 import android.location.Address;
 import android.location.Criteria;
 import android.location.Geocoder;
 import android.location.Location;
 import android.location.LocationListener;
 import android.location.LocationManager;
 import android.os.Bundle;
 import android.util.Log;
 import android.widget.Toast;

 public class MainActivity extends Activity {
     @Override
     public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //获取到LocationManager对象
        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        //创建一个Criteria对象
        Criteria criteria = new Criteria();
        //设置粗略精确度
        criteria.setAccuracy(Criteria.ACCURACY_COARSE);
        //设置是否需要返回海拔信息
        criteria.setAltitudeRequired(false);
        //设置是否需要返回方位信息
        criteria.setBearingRequired(false);
        //设置是否允许付费服务
        criteria.setCostAllowed(true);
        //设置电量消耗等级
        criteria.setPowerRequirement(Criteria.POWER_HIGH);
        //设置是否需要返回速度信息
        criteria.setSpeedRequired(false);

        //根据设置的Criteria对象,获取最符合此标准的provider对象
        String currentProvider = locationManager.getBestProvider(criteria, true);
        Log.d("Location", "currentProvider: " + currentProvider);
        //根据当前provider对象获取最后一次位置信息
        Location currentLocation = locationManager.getLastKnownLocation(currentProvider);
        //如果位置信息为null,则请求更新位置信息
        if(currentLocation == null){
            locationManager.requestLocationUpdates(currentProvider, 0, 0, locationListener);
        }
        //直到获得最后一次位置信息为止,如果未获得最后一次位置信息,则显示默认经纬度
        //每隔10秒获取一次位置信息
        while(true){
            currentLocation = locationManager.getLastKnownLocation(currentProvider);
            if(currentLocation != null){
                Log.d("Location", "Latitude: " + currentLocation.getLatitude());
                Log.d("Location", "location: " + currentLocation.getLongitude());
                break;
            }else{
                Log.d("Location", "Latitude: " + 0);
                Log.d("Location", "location: " + 0);
            }
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                 Log.e("Location", e.getMessage());
            }
        }

        //解析地址并显示
        Geocoder geoCoder = new Geocoder(this);
        try {
            int latitude = (int) currentLocation.getLatitude();
            int longitude = (int) currentLocation.getLongitude();
            List

<address> list = geoCoder.getFromLocation(latitude, longitude, 2);
            for(int i=0; i  75                Address address = list.get(i);
                Toast.makeText(MainActivity.this, address.getCountryName() + address.getAdminArea() + address.getFeatureName(), Toast.LENGTH_LONG).show();
            }
        } catch (IOException e) {
            Toast.makeText(MainActivity.this,e.getMessage(), Toast.LENGTH_LONG).show();
        }

     }

     //创建位置监听器
     private LocationListener locationListener = new LocationListener(){
         //位置发生改变时调用
         @Override
         public void onLocationChanged(Location location) {
             Log.d("Location", "onLocationChanged");
             Log.d("Location", "onLocationChanged Latitude" + location.getLatitude());
                  Log.d("Location", "onLocationChanged location" + location.getLongitude());
         }

         //provider失效时调用
         @Override
         public void onProviderDisabled(String provider) {
             Log.d("Location", "onProviderDisabled");
         }

         //provider启用时调用
         @Override
         public void onProviderEnabled(String provider) {
             Log.d("Location", "onProviderEnabled");
        }

         //状态改变时调用
         @Override
         public void onStatusChanged(String provider, int status, Bundle extras) {
             Log.d("Location", "onStatusChanged");
         }
     };
 }

由于代码里的Criteria对象对位置精度要求并不高,所以一般会返回“network”作为provider,而基于network的定位 往往会存在一定的位置偏差,这对于需要精确定位的应用程序来说,显然不合要求。这时,需要则需要用到基于GPS的定位方法了。具体详情,请看后续博文 Android定位功能(二)。

[转载]FlexPaper+SwfTools实现的在线文档功能

mikel阅读(1187)

[转载]FlexPaper+SwfTools实现的在线文档功能 – penbox – 博客园.

最近一个项目需要实现一个在线浏览文档的功能。准备使用FlexPaper配合Pdf2Swf实现。

主要需求在于:

➔ 文档页数很多,少则几百页,多则上千页。
➔ 相应的文档大小也在50MB以上。

根据需求,将该功能拆分成了三部分:

上传:支持大文件,断点续传。
文件转换服务:在后台进行Pdf转Swf。
在线浏览:分页加载。

其中文件上传部分是我同事实现的,这里主要讲下后台服务和在线浏览部分。

文件转换服务

大体思路是:
后台服务定时扫描文件夹PdfPath,如果发现Pdf文件,则调用Pdf2Swf.exe,将PDF逐页转换成Swf文件,存入SwfPath中的与文件名称对应的文件夹里。

这里使用了SwfTools套件中的Pdf2Swf工具:下载

主要代码:

//PDF转换成SWF
private void ConvertPDFtoSWF(string pdfFile)
{
using (Process p = new Process())
{
SystemLog.CurrentLogger.Debug(string.Format("正在处理 {0} ...", pdfFile));

string pdf2swfExe = "pdf2swf.exe";
string savePath = GetSavePathFromName(pdfFile);

string cmd = pdf2swfExe;
string args = "  -t \"" + pdfFile + "\"  -o \"" + savePath + pdfFile.Split('\\').Last().Replace(".pdf", "")
+ "%.swf\" -s drawonlyshapes -s flashversion=9";

p.StartInfo.FileName = cmd;
p.StartInfo.Arguments = args;
p.StartInfo.UseShellExecute = false;

//此类提供的标准output流只有2k,不要重定向
p.StartInfo.RedirectStandardOutput = false;

p.StartInfo.CreateNoWindow = true;
p.Start();
p.PriorityClass = ProcessPriorityClass.High;
p.WaitForExit();

SystemLog.CurrentLogger.Debug(string.Format("{0} 处理完成。", pdfFile));

if (AppConfiguration.DeleteConvertedPdf)
{
//转换完成后删除Pdf
File.Delete(pdfFile);
SystemLog.CurrentLogger.Debug(string.Format("{0} 已删除。", pdfFile));
}
else
{
//重命名Pdf
File.Move(pdfFile, pdfFile + ".bak");
SystemLog.CurrentLogger.Debug(string.Format("{0} 已重命名。", pdfFile));
}
}
}
gentleface.com free icon set 写服务的时候遇到一个奇怪的Bug,发布为服务的时候,测试用的Pdf文件每次转换到37页的时候就卡住了,但是用命令行进行调试的时候却一切OK。
Google后发现,原来是Process的output流问题:output流只有2KB,而Pdf2Swf会产生大量输出,2KB很快就耗尽了。

之前在测试的时候,发现转换过程中会出现文字丢失的现象。这里使用了-s drawonlyshapes 这个参数,将Pdf全部作为图片转换的。这样虽然保证了兼容性,但是牺牲了空间。作为图片生成的Swf比文本格式的Swf要大不少,不知道大家有没有什么 好的解决方法。

在线浏览

FlexPaper支持分页加载,采用{filename[*,padding],total pages}这种语法即可。

主要代码:

<a id="viewerPlaceHolder" style="width: 800px; height: 600px; display: block;"></a>

<script type="text/javascript">// <!&#91;CDATA&#91;
    var fp = new FlexPaperViewer(
    'FlexPaperViewer',
     'viewerPlaceHolder', { config: {
         SwfFile: 'SwfFolder/<%=Folder %>/{<%=Folder %>&#91;*,0&#93;.swf,<%=PageNum %>}',
         localeChain: "zh_CN", //中文
         Scale: 1,
         ZoomTransition: 'easeOut',
         ZoomTime: 0.5,
         ZoomInterval: 0.2,
         FitPageOnLoad: false,
         FitWidthOnLoad: false,
         PrintEnabled: true,
         FullScreenAsMaxWindow: false,
         ProgressiveLoading: false,
         MinZoomSize: 0.2,
         MaxZoomSize: 5,
         SearchMatchAll: false,
         InitViewMode: 'Portrait',

         ViewModeToolsVisible: true,
         ZoomToolsVisible: true,
         NavToolsVisible: true,
         CursorToolsVisible: true,
         SearchToolsVisible: true
     }
     });
// &#93;&#93;></script>
warning FlexPaper无法载入中文文件名。如果右上角的圈圈一直在转,注意是不是文件名称的问题。

参考文章

c# System.Diagnostics.Process 调用外部程序时WaitForExit锁死问题分析及解决方案

FlexPaper+SWFTools 实现仿百度文库及一些小问题

Pdf2Swf命令行参数

解决FlexPaper分页分段加载问题

源码

分页加载:FlexPaper.zip

文件转换服务:PDFtoSWFService.zip

[转载]ASP.NET MVC3实战系列(三):MVC3中使用依赖注入(IOC)

mikel阅读(821)

[转载]ASP.NET MVC3实战系列(三):MVC3中使用依赖注入(IOC) – 王德水 – 博客园.

ASP.NET MVC3实战系列(二):面向接口编程,提高系统可测试性。 中我们说之前的程序虽然可以单元测试。

第一就是我们暴露了HomeController的repository的属性。

第二我们在类内部new了一个对象,假如我们这次是从数据库中得到Lovers,下次想从文件或者Web Service里去数据时,我们必须修改Controller里的代码。

在这一节里我们引入一个依赖注入的工具Ninject.

image

点击安装

image

修改HomeController为如下代码

image

这样我们就不需要暴露属性了,修改对应的单元测试为如下图所示。测试顺利通过

image

但是,当我们运行程序时出错了,因为MVC在实例化Controller时出错,因为没有无参构造函数参数,而我们确要实例化带参的构造函数。

image

我们需要自己实例化Controller,所以我们需要建立一个ControllerFactory并让应用程序使用我们自己的这个ControllerFactory

image

然后在Global.asax.cs里指定使用这个ControllerFactory

image

按F5运行程序又运行正常了

image

至此,这个应用程序已经易于测试了,而且面向了接口编程。易于扩展。

最后,打个小广告:西安分公司急聘如下人员,有意者直接联系我,左边侧栏有我的联系方式,博客园招聘频道有详细描述 http://job.cnblogs.com/offer/13800/

基本要求:
4年以上C#开发经验, .Net基础扎实,熟练使用.Net3.5新特性。
精通ASP.NET Web开发。
熟练使用WCF.
熟练使用ORM,LINQ TO SQL /Entity Framework或者NHibernate.
熟练使用JavaScript, JQuery.
熟悉Web标准,熟悉HTML&CSS.
熟悉SQL Server, 熟练掌握T-SQL,存储过程。
英语读写熟练,可以看懂英文需求,可以和客户流畅的用英语文字沟通(MSN/Skype)
良好的编码习惯。

熟悉下面任意一项优先:
熟悉敏捷开发者优先
英语听说熟练者优先
熟悉ASP.NET MVC者优先。
熟悉WPF者优先
熟悉Silverlight优先
有系统架构经验者优先,有单元测试或者TDD经验者优先。

作者: 王德水
出处:http://www.cnblogs.com/cnblogsfans
版权:本文版权归作者和博客园共有,转载需经作者同意。

[转载]ASP.NET MVC3实战系列(二):面向接口编程,提高系统可测试性。

mikel阅读(901)

[转载]ASP.NET MVC3实战系列(二):面向接口编程,提高系统可测试性。 – 王德水 – 博客园.

ASP.NET MVC 使用MVC的架构,其架构本身就使应用程序更易于测试,但这并不意味着可以随便写出易于测试的程序。我们都知道单元测试在系统开发有着很重要的作用。

我们来写这样的一个程序,系统获取某个坏男人的情人信息,然后发送给他老婆。

1. 建一个Lover的ASP.NET MVC3项目

image

我们需要1个实体类,存储男人,情人和老婆的信息。

image

然后我们需要一个LoverRepository来获取某个人的情人,这里就想成从数据库取数据。我们这里先返回固定的数据

image

建一个HomeController, 代码如下

image

建立一个Index视图

image

建立一个Send 视图

image

F5运行

image

image

2. 重构这个小程序。

我们可以看到如果我们想测试HomeController里Send的这个Action,如果LoverRepository没有开发完或者出错,我们将无法测试

image

image

可以看到单元测试出错了。

image

那么我们如何来隔离LoveRepository呢?我们都知道面向接口编程可以提高系统的可测试性。

打开LoveRepository.cs, 右键重构为接口:

image

image

image

image

为了容易测试,我们把这个接口属性设为公有。

image

这时我们再自己可以实现一个FakeRepository继承ILoverRepository这个接口,这样就测试通过了。

image

但是这样有几个问题:

第一就是我们暴露了HomeController的repository的属性。

第二我们在类内部new了一个对象,假如我们这次是从数据库中得到Lovers,下次想从文件或者Web Service里去数据时,我们必须修改Controller里的代码。

第三我们需要自己写一个Fake类。

要想解决这些问题,下一节我们将讨论ASP.NET MVC3里如何使用IOC来解决对象的依赖问题。

最后,打个小广告:西安分公司急聘如下人员,有意者直接联系我,左边侧栏有我的联系方式,博客园招聘频道有详细描述 http://job.cnblogs.com/offer/13800/

基本要求:
4年以上C#开发经验, .Net基础扎实,熟练使用.Net3.5新特性。
精通ASP.NET Web开发。
熟练使用WCF.
熟练使用ORM,LINQ TO SQL /Entity Framework或者NHibernate.
熟练使用JavaScript, JQuery.
熟悉Web标准,熟悉HTML&CSS.
熟悉SQL Server, 熟练掌握T-SQL,存储过程。
英语读写熟练,可以看懂英文需求,可以和客户流畅的用英语文字沟通(MSN/Skype)
良好的编码习惯。

熟悉下面任意一项优先:
熟悉敏捷开发者优先
英语听说熟练者优先
熟悉ASP.NET MVC者优先。
熟悉WPF者优先
熟悉Silverlight优先
有系统架构经验者优先,有单元测试或者TDD经验者优先。

作者: 王德水
出处:http://www.cnblogs.com/cnblogsfans
版权:本文版权归作者和博客园共有,转载需经作者同意。

[转载]34个漂亮的应用程序后台管理系统界面(系列二)

mikel阅读(883)

[转载]34个漂亮的应用程序后台管理系统界面(系列二) – 梦想天空(山边小溪) – 博客园.

今天这篇文章收集了34个漂亮的应用程序后台管理界面分享给大家。这些界面都是来自themeforest网站,虽然直接下载需要付费的,不过 大部分都提供了在线预览,所以完全能够复制下来,有的提供了预览图,设计师可以根据预览图自己设计。希望这些漂亮的后台管理界面设计案例能帮助到你。(有 登录界面的,点击登录即可进入后台界面)

Flexy Admin


34个漂亮的应用程序后台管理系统界面

Broom Cupboard Admin Skin


34个漂亮的应用程序后台管理系统界面

Fresh CMS


34个漂亮的应用程序后台管理系统界面

Ultimate Admin Panel Solution


34个漂亮的应用程序后台管理系统界面

Titanium


34个漂亮的应用程序后台管理系统界面

Wide Admin


34个漂亮的应用程序后台管理系统界面

AP Admin Panel


34个漂亮的应用程序后台管理系统界面

Ninja Admin


34个漂亮的应用程序后台管理系统界面

Sleek Admin Skin


34个漂亮的应用程序后台管理系统界面

Pro Admin Template


34个漂亮的应用程序后台管理系统界面

您可能还喜欢

[原创]DEDECMS仿站笔记1:自定义联动类别调用

mikel阅读(1141)

1. PrintAutoFieldsAdd 载入自定义表单(用于发布):
文件:inc/inc_archives_function.php
行号:472
函数声明:function PrintAutoFieldsAdd(&$fieldset,$loadtype=’all’)
参数:
$fieldset:自定义模型的字段集合
$loadtype:价值类型有两种:all ,autofield;autofield
功能说明:
发布自定义模型界面调用时,拼装自定义模型的表单。

2. DedeTagParse Dede织梦模板类
文件:include\dedetag.class.php
行号:70
类声明:class DedeTagParse
方法:
 LoadSource($str):载入模板字符串,调用data/tplcache/MD5($str).inc的模板文件,然后调用LoadTemplate()方法解析模板
 LoadTemplate($filename):载入模板文件 然后调用ParseTemplet()解析模板
 ParseTemplet():解析模板
3. 模板列表调用内容模型格式数据写法:
{dede:arclist channelid=’18’ addfields=’xuebu,course_author’}

  • [field:course_author/]aaa
  • {/dede:arclist}
    说明:
    Channelid:内容模型管理中的ID号
    AddFields:定义的字段名,需要在内容模型管理中的“列表附加字段”中添加

    4. 自定义联动类别信息的调用方法:
    1)函数编写
    打开 /include/extend.func.php 文件(注:本文件为自定义函数接口文件,若不存在,请自行创建),在最后一行的?>上添加如下代码:
    function Getsysenum($fields,$egroup){
    global $dSQL;
    $row = $dsql->GetOne(“select * from dede_sys_enum where evalue = ‘”.$fields.”‘and egroup=’”.$egroup. “’”);
    if(!is_array($row)){
    return “联动类别不存在“;
    }
    else{
    return $row[‘ename’];
    }
    }
    保存关闭即可!
    2)函数调用
    这个函数的调用非常简单,只需要将“枚举值”传递过来即可,这个缓存组名通常也就是内容模型中的自定义联动菜单字段名:
    function Getsysenum(‘枚举值’,’联动组名’);
    3)调用实例
    我们来看一下调用的实例代码:
    {dede:arclist titlelen=’60’ row=’8′ channelid=’1′ addfields=’nativeplace’}

  • [field:nativeplace function=”Getsysenum(@me,’ nativeplace’)”/]
    [field:title /]
  • {/dede:arclist}
    其中[field:nativeplace function=”Getsysenum(@me,’ nativeplace’)”/] 就是将nativeplace字段进行Getsysenum函数处理。

    5. 联动类别信息存储表dede_sys_enum:
    字段 类型 长度 是否主键 描述
    ID Smallint 6 是
    Ename Char 30 分类名称
    Evalue Smallint 6 分类ID
    Egroup Char 20 分组名称
    Disorder Smallint 5 排列顺序
    Issign Tinyint 1 是否系统1=系统 0=非系统

    6. 扩展函数编写文件/include/extend.func.php:
    通过上面的扩展查询分类的函数可见可以自定义扩展函数在/include/extend.func.php文件中,用于标签中进行调用,
    于是编写了扩展函数查询给定分类组合的,一级分类信息的扩展数:
    Function GetSysEnum($egroup,$level)
    global $dSQL;
    $row = $dsql->GetOne(“select ename from dede_sys_enum where evalue like ‘%”.$level.”‘and egroup=’”.$egroup. “’”);
    if(!is_array($row)){
    return “联动类别不存在“;
    }
    else{
    return $row[‘ename’];

    调用方式:
    Function=’GetSysEnum(‘xuebu’,’0’)’