您的位置:首页 > 其它

DiscuzNT使用Silverlight进行多文件上传(上) 推荐

2009-04-08 08:47 405 查看
注:本文的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插件的信息绑定,也就是之前第二张图中所说的信息内容(红框部分)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息