DiscuzNT使用Silverlight进行多文件上传

      注:本文的HTM页面均位于Discuz.Web项目中,大家可以到官方下面最终的程序。

      在去年我曾写过一篇文章:“推荐一个Silverlight多文件(大文件)上传的开源项目”。之后
有不少朋友询问这个项目示例在开发和配置上的一些问题。当时因为时间有限没有做过多的说明,
导致有些问题在大家下载完源码之后运行时才出现。今天就以这个项目为原型,简要介绍一下在
DiscuzNT上是如果在该项目基本上,通过完善权限管理,文件大小控制,添加缩略图效果等功能
来大体阐述一下如果开发一个真正的silverlight应用,而不是一个简单的DEMO.

      当然本文中所列出的源码是通过reflector获取并添加相应注释的。最终的源码还是要以开放
出来的为准,呵呵:)


      好了,开始今天的正文吧!
   
      首先,看一下这个插件在DiscuzNT中的实际运行效果:    
    
    
    
    
    


    

 

     

      当我们在网页中点击“批量上传”按钮时,会运行如下JS脚本(文件位于Discuz.Web\
templates\default_postattachments.htm):

function  LoadSilverlight(pluginID, max) {
     
     Silverlight.createObject(
         
" silverlight/UploadFile/ClientBin/MultiFileUpload.xap "
         $(
" silverlightControlHost " ),         
         pluginID,                         
         {     
             width: 
' 500 ' ,
             height: 
' 440 ' ,
             inplaceInstallPrompt: 
' true ' ,
             isWindowless: 
' true ' ,
             background: 
' transparent ' ,
             version: 
' 2.0 ' ,
             autoUpgrade: 
' true '
         },
         {
             onLoad: onLoad, 
             onError: onSilverlightError
         },
         
<% csharp %>
         string authToken 
=  Discuz.Common.DES.Encode(oluserinfo.Olid.ToString()  +   " , "   +  
         oluserinfo.Username.ToString(), oluserinfo.Password.Substring(
0 10 )).Replace( " + " " [ " );
         
<% / csharp%> 
          " forumid={forumid},authToken={authToken},max= "   +  max,
         
"" );
}

 

    其会将当前版块id(forumid),认证Token,最大上传数等信息以参数形式传给SL插件,而我专门定
义了一个方法用于获取相应的参数并绑定到sl变量,如下(Page.xaml.cs): 

///   <summary>
 
///  加载配置参数
 
///   </summary>
 
///   <param name="initParams"></param>
  private   void  LoadConfiguration(IDictionary < string string >  initParams)
 {
     
string  tryTest  =   string .Empty;

     
// 加载定制配置信息串
     _customParams  =  initParams[ " forumid " ];

     
if  (initParams.ContainsKey( " MaxUploads " &&   ! string .IsNullOrEmpty(initParams[ " MaxUploads " ]))
         
int .TryParse(initParams[ " MaxUploads " ],  out  _maxUpload);            

     
if  (initParams.ContainsKey( " MaxFileSizeKB " &&   ! string .IsNullOrEmpty(initParams[ " MaxFileSizeKB " ]))
     {
         
if  ( int .TryParse(initParams[ " MaxFileSizeKB " ],  out  _maxFileSize))
             _maxFileSize 
=  _maxFileSize  *   1024 ;
     }

     
if  (initParams.ContainsKey( " FileFilter " &&   ! string .IsNullOrEmpty(initParams[ " FileFilter " ]))
         _fileFilter 
=  initParams[ " FileFilter " ];          

     
if  (initParams.ContainsKey( " forumid " &&   ! string .IsNullOrEmpty(initParams[ " forumid " ]))
         _forumid 
=  Utils.StrToInt(initParams[ " forumid " ],  0 );

     
if  (initParams.ContainsKey( " max " &&   ! string .IsNullOrEmpty(initParams[ " max " ]))
         _maxAttachments 
=  Utils.StrToInt(initParams[ " max " ],  0 );

     CredentialInfo _creInfo
=  Utils.GetCredentialInfo();
     
if  (_creInfo.UserID  <=   0 )
     {
         ShowMessageBox(
" 您未登陆系统 " );
         SetUploadButton(
false );
         
return ;
     }
     
else
     {
         MixObjectsSoapClient _client 
=  Utils.CreateServiceClient();
         _client.GetAttachmentUploadSetCompleted 
+=   new  EventHandler < GetAttachmentUploadSetCompletedEventArgs >
                                (_client_GetAttachmentUploadSetCompleted);
         _client.GetAttachmentUploadSetAsync(_creInfo, _forumid);
     }
 }

        
        
      大家看到在该方法在获取相应初始化参数(initParams)后,会调用Utils.GetCredentialInfo()来获取
 用户登陆信息:

///   <summary>
///  获取认证信息
///   </summary>
///   <returns></returns>
public   static  CredentialInfo GetCredentialInfo()
{
        CredentialInfo _creinfo 
=   new  CredentialInfo();
        _creinfo.UserID 
=  Utils.StrToInt(Utils.GetCookie( " userid " ),  0 );
        _creinfo.Password 
=  Utils.GetCookie( " password " );

        
if  (App.GetInitParmas.ContainsKey( " authToken " &&   ! string .IsNullOrEmpty(App.GetInitParmas[ " authToken " ]))
            _creinfo.AuthToken 
=  App.GetInitParmas[ " authToken " ];

        
if  (App.GetInitParmas.ContainsKey( " forumid " &&   ! string .IsNullOrEmpty(App.GetInitParmas[ " forumid " ]))
            _creinfo.ForumID 
=  StrToInt(App.GetInitParmas[ " forumid " ],  0 );

        
return  _creinfo;
}

        
    其中最主要的就是获取相应的UserID,而这个操作是交给GetCookie来完成的:
      

public   static   string  GetCookie(String key)
{
     
if  ( string .IsNullOrEmpty(HtmlPage.Document.Cookies))
         
return   null ;

     
// 找到想应的cookie键值
      string  result  =  (from c  in
                          (from cookie 
in  HtmlPage.Document.Cookies.Split( ' ; ' )
                           
where  cookie.Contains(key  +   " = " )
                           select cookie.Split(
' & ' )).FirstOrDefault()
                      
where  c.Contains(key  +   " = " )
                      select c).FirstOrDefault().ToString();

     
if ( string .IsNullOrEmpty(result))
         
return   null ;

     
return  result.Substring(result.IndexOf(key  +   " = " +  key.Length  +   1 );
}

 

      其主要是通过用户本地的Cookie,来获取相应的用户信息。
   
      如果用户的Cookie有效(已登陆过),则直接获取该用户所在用户组及其它相关联的权限信息,
 如果无效,则提示用户登陆,同时将SL中的几个上传按钮“置灰”,以免未登陆的用户上传附件。

  
      下面就是其向服务器请求谁信息的代码:

 MixObjectsSoapClient _client  =  Utils.CreateServiceClient();
 _client.GetAttachmentUploadSetCompleted 
+=   new  EventHandler < GetAttachmentUploadSetCompletedEventArgs >
                               (_client_GetAttachmentUploadSetCompleted);
 _client.GetAttachmentUploadSetAsync(_creInfo, _forumid);

     
      上面客户端请求下面的服务端代码:     

///   <summary>
///  通过指定用户认证信息来获得该用户的上传设置信息
///   </summary>
///   <param name="creinfo"> 用户认证信息 </param>
///   <returns></returns>
[WebMethod]
public  UploadSetInfo GetAttachmentUploadSet(CredentialInfo creinfo)
{
    
if  (AuthenticateUser(creinfo))
    {
        UserInfo userinfo 
=  Discuz.Forum.Users.GetUserInfo(creinfo.UserID);
        
if  (userinfo  ==   null )
            
return   new  UploadSetInfo( "" "" 0 0 false 0 " 当前用户信息无效,请尝试刷新 " );

        UserGroupInfo usergroupinfo 
=  Discuz.Forum.UserGroups.GetUserGroupInfo(userinfo.Groupid);
        
if  (usergroupinfo  ==   null )
            
return   new  UploadSetInfo( "" "" 0 0 false 0 " 当前用户所属用户组信息无效 " );


        ForumInfo forum 
=  Discuz.Forum.Forums.GetForumInfo(creinfo.ForumID);
        
if  (forum  ==   null )
            
return   new  UploadSetInfo( null null 0 0 false 0 " 当前版块信息无效,请尝试刷新 " );

        
// 得到用户可以上传的文件类型
        StringBuilder sbAttachmentTypeSelect  =   new  StringBuilder();
        
if  ( ! usergroupinfo.Attachextensions.Trim().Equals( "" ))
        {
            sbAttachmentTypeSelect.Append(
" [id] in ( " );
            sbAttachmentTypeSelect.Append(usergroupinfo.Attachextensions);
            sbAttachmentTypeSelect.Append(
" ) " );
        }

        
if  ( ! forum.Attachextensions.Equals( "" ))
        {
            
if  (sbAttachmentTypeSelect.Length  >   0 )
                sbAttachmentTypeSelect.Append(
"  AND  " );

            sbAttachmentTypeSelect.Append(
" [id] in ( " );
            sbAttachmentTypeSelect.Append(forum.Attachextensions);
            sbAttachmentTypeSelect.Append(
" ) " );
        }
        
string  attachextensions  =  Discuz.Forum.Attachments.GetAttachmentTypeArray(sbAttachmentTypeSelect.ToString());
        
string  attachextensionsnosize  =  Discuz.Forum.Attachments.GetAttachmentTypeString(sbAttachmentTypeSelect.ToString());

        
// 得到今天允许用户上传的附件总大小(字节)
         int  MaxTodaySize  =   0 ;
        
if  (creinfo.UserID  >   0 )
            MaxTodaySize 
=  Discuz.Forum.Attachments.GetUploadFileSizeByuserid(creinfo.UserID);

        
int  attachsize  =  usergroupinfo.Maxsizeperday  -  MaxTodaySize; // 今天可上传大小

        
bool  canpostattach  =   false // 是否允许上传附件
        
// 是否有上传附件的权限
         if  (Discuz.Forum.Forums.AllowPostAttachByUserID(forum.Permuserlist, creinfo.UserID))
            canpostattach 
=   true ;
        
else
        {
            
if  (forum.Postattachperm  ==   "" )
            {
                
if  (usergroupinfo.Allowpostattach  ==   1 )
                    canpostattach 
=   true ;
            }
            
else
            {
                
if  (Discuz.Forum.Forums.AllowPostAttach(forum.Postattachperm, usergroupinfo.Groupid))
                    canpostattach 
=   true ;
            }
        }
        
return   new  UploadSetInfo(attachextensions, attachextensionsnosize, MaxTodaySize, attachsize, 
                            canpostattach , usergroupinfo.Maxattachsize, 
"" );
    }

    
return   new  UploadSetInfo( "" "" 0 0 false 0 " 当前用户信息无效,请尝试刷新 " );
}

 

     该方法的首先会访问AuthenticateUser方法来进行用户身份验证:
   
/// <summary>
/// WEB权限认证

///   </summary>
///   <param name="creinfo"> 认证信息 </param>
///   <returns> 是否通过验正 </returns>
private   bool  AuthenticateUser(CredentialInfo creinfo)
{
    
if  (creinfo.ForumID  >   0 )
    {
        
int  olid  =  Discuz.Forum.OnlineUsers.GetOlidByUid(creinfo.UserID);
        
if  (olid  >   0 )
        {
            OnlineUserInfo oluserinfo 
=  Discuz.Forum.OnlineUsers.GetOnlineUser(olid);
            
if  (oluserinfo.Userid  ==  creinfo.UserID  &&  
                Utils.UrlEncode(Discuz.Forum.ForumUtils.SetCookiePassword(oluserinfo.Password, 
                 GeneralConfigs.GetConfig().Passwordkey)) 
==  creinfo.Password  && // 检测用户id和口令
                creinfo.AuthToken  ==  DES.Encode( string .Format( " {0},{1} " , oluserinfo.Olid.ToString(), 
                  oluserinfo.Username.ToString()), oluserinfo.Password.Substring(
0 10 )).Replace( " + " " [ " )) // 检查认证信息
            {
                
return   true ;
            }
        }
    }
    
return   false ;
}

    
    其会对用户的UserId与用户在线表中的数据进行比对,以确保其信息有效,同时还会检查AuthToken
来避免用户通过伪造用户信息来进行信息提交。当上面方法返回TRUE时,则将对用户所在版块的权限信息
进行获取,并返回一个名为UploadSetInfo类实例,其包括:

    1.用户可以上传的文件类型
    2.用户可以上传的文件类型(不带上传数据大小)
    3.得到今天允许用户上传的附件总大小(字节)
    4.是否允许上传附件
    5.单个附件大小
    6.最大允许上传的附件数
    7.错误信息

     

#region  上传设置信息类
    
///   <summary>
    
///  上传设置信息类
    
///   </summary>
     public   class  UploadSetInfo
    {
        
public  UploadSetInfo()
        { }

        
public  UploadSetInfo( string  attachExtensions,  string  attachExtensionsNoSize,  int  maxTodaySize, 
                  
int  attachSize,  bool  canPostAttach,  int  maxAttachSize,  string  errMessage)
        {
            m_attachExtensions 
=  attachExtensions;
            m_attachExtensionsNoSize 
=  attachExtensionsNoSize;
            m_maxTodaySize 
=  maxTodaySize;
            m_attachSize 
=  attachSize;
            m_canPostAttach 
=  canPostAttach;
            m_maxAttachSize 
=  maxAttachSize;
            m_errMessage 
=  errMessage;
            m_maxAttachments 
=  GeneralConfigs.GetConfig().Maxattachments;
        }

        
private   string  m_attachExtensions;
        
///   <summary>
        
///  用户可以上传的文件类型
        
///   </summary>
         public   string  AttachExtensions
        {
            
get  {  return  m_attachExtensions; }
            
set  { m_attachExtensions  =  value; }
        }

        
private   string  m_attachExtensionsNoSize;
        
///   <summary>
        
///  用户可以上传的文件类型(不带上传数据大小)
        
///   </summary>
         public   string  AttachExtensionsNoSize
        {
            
get  {  return  m_attachExtensionsNoSize; }
            
set  { m_attachExtensionsNoSize  =  value; }
        }

        
private   int  m_maxTodaySize;
        
///   <summary>
        
///  得到今天允许用户上传的附件总大小(字节)
        
///   </summary>
         public   int  MaxTodaySize
        {
            
get  {  return  m_maxTodaySize; }
            
set  { m_maxTodaySize  =  value; }
        }

        
private   int  m_attachSize;
        
///   <summary>
        
///  今天可上传的大小
        
///   </summary>
         public   int  AttachSize
        {
            
get  {  return  m_attachSize; }
            
set  { m_attachSize  =  value; }
        }

        
private   bool  m_canPostAttach;
        
///   <summary>
        
///  是否允许上传附件
        
///   </summary>
         public   bool  CanPostAttach
        {
            
get  {  return  m_canPostAttach; }
            
set  { m_canPostAttach  =  value; }
        }

        
private   int  m_maxAttachSize;
        
///   <summary>
        
///  单个附件大小
        
///   </summary>
         public   int  MaxAttachSize
        {
            
get  {  return  m_maxAttachSize; }
            
set  { m_maxAttachSize  =  value; }
        }

        
private   string  m_errMessage;
        
///   <summary>
        
///  错误信息
        
///   </summary>
         public   string  ErrMessage
        {
            
get  {  return  m_errMessage; }
            
set  { m_errMessage  =  value; }
        }

        
private   int  m_maxAttachments;
        
///   <summary>
        
///  最大允许上传的附件数
        
///   </summary>
         public   int  Maxattachments
        {
            
get  {  return  m_maxAttachments; }
            
set  { m_maxAttachments  =  value; }
        }
    }
    
#endregion

 
     如果一切顺利,客户端会获取相应的UploadSetInfo实例信息来进行SL插件的信息绑定,也就是之前第
二张图中所说的信息内容(红框部分)。


     如果当前用户通过验证,就可以通过SL上传附件了,因为用户上传的附件要进行实时统计,以即时更新
已上传附件的总和大小,来防止用户上传过量的附件),所以我在打开文件对话框事件中加入了到已上传
附件大小的统计以便进行控件:

///   <summary>
///  选择文件对话框事件
///   </summary>
///   <param name="sender"></param>
///   <param name="e"></param>
private   void  SelectFilesButton_Click( object  sender, RoutedEventArgs e)
{
    
if  (AttachmentList.Count  >=  _maxAttachments)
    {
        ShowMessageBox(
" \r\n您上传的文件数已达到系统规定的上限:  "   +  _maxAttachments  +   " . " );
        
return ;
    }

    OpenFileDialog ofd 
=   new  OpenFileDialog();
    ofd.Multiselect 
=   true ;

    
try
    {
        
if ( ! string .IsNullOrEmpty(_fileFilter))
            ofd.Filter 
=  _fileFilter;
    }
    
catch (ArgumentException ex)
    {
        ShowMessageBox(
" 错误的文件过滤配置:  "   +  ex.Message);
    }

    
if  (ofd.ShowDialog()  ==   true )
    {
        
if  (filecount  ==   0 )
            filecount 
=  AttachmentList.Count;

        
foreach  (FileInfo file  in  ofd.Files)
        {
            
if  ((filecount  +   1 >  _maxAttachments)
            {
                ShowMessageBox(
" \r\n您上传的文件数已达到系统规定的上限:  "   +  _maxAttachments  +   " . " );
                
return ;
            }
            filecount
++ ;

            
string  fileName  =  file.Name;
            UserFile userFile 
=   new  UserFile();
            userFile.FileName 
=  file.Name;
            userFile.FileStream 
=  file.OpenRead();
            userFile.ViewStream 
=  file.OpenRead();

            
// 总上传值在规定范围内时
             if  (_todayAttachSize  <  (_todayUploadSize  +  _wantUploadSize  +  userFile.FileStream.Length))
            {
                ShowMessageBox(
" \r\n当前附件大小:  "   +  Math.Round(( decimal )userFile.FileStream.Length  /   1024   /   1024 2 )
                 
+   "  MB, 而今天还可以上传: "   +  Math.Round(( decimal )(_todayAttachSize  -  _todayUploadSize)  /   1024   /   1024 2 +   "  MB. " );
                
break ;
            }
            
// 当单个文件大小大于最大上传附件尺寸时
             if  (userFile.FileStream.Length  >  _maxFileSize)
            {
                ShowMessageBox(
" \r\n当前附件大小:  "   +  Math.Round(( decimal )userFile.FileStream.Length  /   1024   /   1024 2 )
                
+   "  MB, 而单个附件允许最大尺寸为:  "   +  Math.Round(( decimal )_maxFileSize  /   1024   /   1024 2 +   "  MB.\r\n " );
                
break ;
            }

            
// 向文件列表中添加文件信息
            _files.Add(userFile);
            _wantUploadSize 
+=  userFile.FileStream.Length;  
        }
    }
}       

    
     这样就从选择附件方面杜绝了上述情况的发生。    
    
     之后,当用户选择了上传的附件,并加载到上传列表后点击上传按钮时,SL会将当前要上传的文件进行
切块(4 * 4096 byte),并分块上传,代码如下:

 

///   <summary>
///  上传文件
///   </summary>
private   void  UploadAdvanced()
{
    
    
byte [] buffer  =   new   byte [ 4   *   4096 ];
    
int  bytesRead  =  _file.FileStream.Read(buffer,  0 , buffer.Length);

    
// 文件是否上传完毕?
     if  (bytesRead  !=   0 )
    {
        _dataSent 
+=  bytesRead;

        
if  (_dataSent  ==  _dataLength)
            _lastChunk 
=   true ; // 是否是最后一块数据,这样WCF会在服务端根据该信息来决定是否对临时文件重命名

        
// 上传当前数据块
        _client.StoreFileAdvancedAsync(_file.FileName, buffer, bytesRead, _initParams, _firstChunk, _lastChunk, 
                 Utils.GetCredentialInfo());

        
// 在第一条消息之后一直为false
        _firstChunk  =   false ;

        
// 通知上传进度修改
        OnProgressChanged();
    }
    
else
    {
        
// 当上传完毕后
        _file.FileStream.Dispose();
        _file.FileStream.Close();

        _client.ChannelFactory.Close();          
    }
}

       
     注意上面的StoreFileAdvancedAsync方法就是要请求的服务端代码,下面即是其服务端代码:     

  ///   <summary>
 
///  上传附件
 
///   </summary>
 
///   <param name="fileName"> 文件名称 </param>
 
///   <param name="data"> 上传的字节数据 </param>
 
///   <param name="dataLength"> 数据长度 </param>
 
///   <param name="parameters"> 上传参数 </param>
 
///   <param name="firstChunk"> 是否第一块数据 </param>
 
///   <param name="lastChunk"> 是否最后一块数据 </param>
 [WebMethod]
 
public  AttachmentInfo StoreFileAdvanced( string  fileName,  byte [] data,  int  dataLength,  string  parameters, 
                                        
bool  firstChunk,  bool  lastChunk, CredentialInfo creinfo)
 {
     
if  (AuthenticateUser(creinfo))
     {
         UploadSetInfo uploadSetInfo 
=  GetAttachmentUploadSet(creinfo);
         
string  fileextname  =  Utils.CutString(fileName, fileName.LastIndexOf( " . " +   1 ).ToLower();

         
if  (uploadSetInfo.CanPostAttach  &&  uploadSetInfo.AttachExtensionsNoSize.IndexOf(fileextname)  >=   0   &&  
             uploadSetInfo.AttachSize 
>  dataLength  &&  Utils.StrIsNullOrEmpty(uploadSetInfo.ErrMessage))
         {
             
string  uploadFolder  =  GetUploadFolder(fileName, creinfo.ForumID.ToString());
             
string  tempFileName  =  fileName  +  _tempExtension;

             
if  (firstChunk)
             {
                 
// 删除临时文件
                  if  (File.Exists(@HostingEnvironment.ApplicationPhysicalPath  +   " /upload/temp/ "   +  tempFileName))
                     File.Delete(@HostingEnvironment.ApplicationPhysicalPath 
+   " /upload/temp/ "   +  tempFileName);

                 
// 删除目录文件
                  if  (File.Exists(uploadFolder  +   " / "   +  fileName))
                     File.Delete(uploadFolder 
+   " / "   +  fileName);
             }


             FileStream fs 
=  File.Open(@HostingEnvironment.ApplicationPhysicalPath  +   " /upload/temp/ "   +  
                                        tempFileName, FileMode.Append);
             fs.Write(data, 
0 , dataLength);
             fs.Close();

             
if  (lastChunk)
             {
                 File.Move(HostingEnvironment.ApplicationPhysicalPath 
+   " /upload/temp/ "   +  tempFileName, 
                                       uploadFolder 
+   " / "   +  fileName);
                 
return  Discuz.Forum.Attachments.GetAttachmentInfo(AddAttachment(fileName, creinfo));
             }
         }
     }
     
return   null ;
 }

     上面代码会将客户端发送过来的分块数据进行组装到临时文件中,当该文件的所有分块数据传输完毕,
 就会将该临时文件移动到指定的附件文件夹中,同时删除相应临时数据。大家注意到了,在该方法开始部分
 还调用了AuthenticateUser方法(之前说明),这主要就是对安全性的考虑,必定HTTP是一种无状态协议呀。
 
     上面的代码中这一行判断:

if  (uploadSetInfo.CanPostAttach  &&  uploadSetInfo.AttachExtensionsNoSize.IndexOf(fileextname)  >=   0  
    
&&  uploadSetInfo.AttachSize  >  dataLength  &&
             Utils.StrIsNullOrEmpty(uploadSetInfo.ErrMessage))

             
     即是对当前用户上传信息(包括已上传附件大小,数量等)进行检验,以免出现上传数据超过系统限制
的情况。

     在该方法的最后一行,会调用AddAttachment(fileName, creinfo)来进行相应附件信息的初始化绑定,
因为论坛中每个主题包括回帖都可以有附件,只不过对附件的扩展名和大小会有限制,所以这里通过该方法
进行封装,下面是其核心代码:


 

///   <summary>
///  添加附件
///   </summary>
///   <param name="fileName"> 文件名称 </param>
///   <param name="creinfo"> 认证信息 </param>
///   <returns> 返回当前插入的附件id </returns>
private   int  AddAttachment( string  fileName, CredentialInfo creinfo)
{
    
string  UploadDir  =  GetUploadFolder(fileName, creinfo.ForumID.ToString());
    AttachmentInfo attachmentinfo 
=   new  AttachmentInfo();
    
string  fileextname  =  Utils.CutString(fileName, fileName.LastIndexOf( " . " +   1 ).ToLower();
    
string  newfilename  =  (Environment.TickCount  &   int .MaxValue).ToString()  +   new  Random().Next( 1000 9999
                       
+   " . "   +  fileextname;

    
try
    {
        
//  如果是bmp jpg png图片类型
         if  ((fileextname  ==   " bmp "   ||  fileextname  ==   " jpg "   ||  fileextname  ==   " jpeg "   ||  fileextname  ==   " png " ))
        {
            
if  (Discuz.Common.Utils.FileExists(UploadDir  +  fileName))
            {
                System.Drawing.Image img 
=  System.Drawing.Image.FromFile(UploadDir  +  fileName);

                
if  (config.Attachimgmaxwidth  >   0   &&  img.Width  >  config.Attachimgmaxwidth)
                    attachmentinfo.Sys_noupload 
=   " 图片宽度为 "   +  img.Width.ToString()  +   " , 系统允许的最大宽度为 "  
                                   
+  config.Attachimgmaxwidth.ToString();

                
if  (config.Attachimgmaxheight  >   0   &&  img.Height  >  config.Attachimgmaxheight)
                    attachmentinfo.Sys_noupload 
=   " 图片高度为 "   +  img.Width.ToString()  +   " , 系统允许的最大高度为 "  
                                   
+  config.Attachimgmaxheight.ToString();

                
if  (config.Watermarkstatus  ==   0 )
                    attachmentinfo.Filesize 
=   new  FileInfo(UploadDir  +  fileName).Length;
                
else
                {
                    
if  (config.Watermarktype  ==   1   &&  File.Exists(Utils.GetMapPath(BaseConfigs.GetForumPath 
                                           
+   " watermark/ "   +  config.Watermarkpic)))
                        Discuz.Forum.ForumUtils.AddImageSignPic(img, UploadDir 
+  newfilename, 
                                        Utils.GetMapPath(BaseConfigs.GetForumPath 
+   " watermark/ "   +  config.Watermarkpic), 
                                        config.Watermarkstatus, config.Attachimgquality, config.Watermarktransparency);
                    
else
                    {
                        
string  watermarkText;
                        watermarkText 
=  config.Watermarktext.Replace( " {1} " , config.Forumtitle);
                        watermarkText 
=  watermarkText.Replace( " {2} " " http:// "   +  DNTRequest.GetCurrentFullHost()  +   " / " );
                        watermarkText 
=  watermarkText.Replace( " {3} " , Utils.GetDate());
                        watermarkText 
=  watermarkText.Replace( " {4} " , Utils.GetTime());

                        Discuz.Forum.ForumUtils.AddImageSignText(img, UploadDir 
+  newfilename, watermarkText,
                            config.Watermarkstatus, config.Attachimgquality, config.Watermarkfontname, config.Watermarkfontsize);
                    }
                    System.IO.File.Delete(UploadDir 
+  fileName);
                    
//  获得加水印后的文件长度
                    attachmentinfo.Filesize  =   new  FileInfo(UploadDir  +  newfilename).Length;
                }
            }
        }
        
else
        {
            System.IO.File.Move(UploadDir 
+  fileName, UploadDir  +  newfilename);
            attachmentinfo.Filesize 
=   new  FileInfo(UploadDir  +  newfilename).Length;
        }
    }
    
catch {}

    
if  (Discuz.Common.Utils.FileExists(UploadDir  +  fileName))
    {
        attachmentinfo.Filesize 
=   new  FileInfo(UploadDir  +  fileName).Length;
        attachmentinfo.Filename 
=  GetDirInfo(fileName, creinfo.ForumID.ToString())  +  fileName;
    }

    
if  (Discuz.Common.Utils.FileExists(UploadDir  +  newfilename))
    {
        attachmentinfo.Filesize 
=   new  FileInfo(UploadDir  +  newfilename).Length;
        attachmentinfo.Filename 
=  GetDirInfo(newfilename, creinfo.ForumID.ToString())  +  newfilename;
    }
    
    attachmentinfo.Uid 
=  creinfo.UserID;
    attachmentinfo.Description 
=  fileextname;
    attachmentinfo.Filetype 
=  GetContentType(fileextname);
    attachmentinfo.Attachment 
=  fileName;
    attachmentinfo.Downloads 
=   0 ;
    attachmentinfo.Postdatetime 
=  DateTime.Now.ToString();
    attachmentinfo.Sys_index 
=   0 ;

    
return  Discuz.Data.DatabaseProvider.GetInstance().CreateAttachment(attachmentinfo);
}

 

    通过上面的方法就实现了将附件与相应的主题进行绑定功能同时为相应的图片附件加上水印。   
    
    到这里,主要的代码就介绍的差不多了。
   
    当用户完成上传之后,点击“返回”按钮时,会触发下面事件:   

///   <summary>
///  返回按钮事件
///   </summary>
///   <param name="sender"></param>
///   <param name="e"></param>
private   void  FinishUpload_Click( object  sender, RoutedEventArgs e)
{
    GetAttachmentList();
}

[ScriptableMember]
public   void  GetAttachmentList()
{
    StringBuilder sb_attachments 
=   new  StringBuilder();
    sb_attachments.Append(
" [ " );
    
foreach  (AttachmentInfo attachmentInfo  in  AttachmentList)
    {
        sb_attachments.Append(
string .Format( " {{'aid' : {0}, 'attachment' : '{1}', 'description' : '{2}',  'filename' : 
                         ' {3} ' ' filesize '  :{ 4 },  ' filetype '  :  ' {5} ' ' Uid '  : { 6 }}}, " ,
            attachmentInfo.Aid,
            attachmentInfo.Attachment,
            attachmentInfo.Description.Trim(),
            attachmentInfo.Filename.Trim(),
            attachmentInfo.Filesize,
            attachmentInfo.Filetype,
            attachmentInfo.Uid
            ));
    }
    
if  (sb_attachments.ToString().EndsWith( " , " ))
        sb_attachments.Remove(sb_attachments.Length 
-   1 1 );

    sb_attachments.Append(
" ] " );

    
// 调用js端注册事件
    javaScriptableObject.OnUploadAttchmentList(JsonCharFilter(sb_attachments.ToString()));
}

 

     GetAttachmentList方法会调用页面的JS事件并将“已上传”的数据发给WEB页面,而相应的页面
事件绑定代码如下(文件位于Discuz.Web\templates\default_postattachments.htm):

function  onLoad(plugin, userContext, sender) {
     
// 只读属性,标识 Silverlight 插件是否已经加载。
      if  (sender.getHost().IsLoaded) {
         $(
" MultiUploadFile " ).content.JavaScriptObject.UploadAttchmentList  =  getAttachmentList;         
     }
 }
 
// 获取silverlight插件已经上传的附件列表
function  getAttachmentList(sender, args) {
     
var  attachment  =  args.AttchmentList;
     
if  (isUndefined(attachment)  ||  attachment  ==   ' [] ' ) {
         BOX_remove(
' silverlightControlHost ' );
         
return ;
     }
     
var  attachmentList  =  eval( " ( "   +  attachment  +   " ) " );

     BOX_remove(
' silverlightControlHost ' );
     addAttachUploaded(attachmentList);     
 }


 
     这样一个SL多文件上传插件就算基本完成了。当然我还写了“缩略图”功能,因为代码很简单就不
多说了。
    
     好了,今天的内容就先到这里了。

     原文链接: http://www.cnblogs.com/daizhj/archive/2009/04/07/1431090.html

     作者: daizhj, 代震军

     Tags: silverlight,discuznt,uploadfile,文件上传  

     网址: http://daizhj.cnblogs.com/  

你可能感兴趣的:(silverlight)