本文共 11504 字,大约阅读时间需要 38 分钟。
为百度文本编辑器UEditor添加附件管理功能
最近朋友的一个项目需要一个文本编辑器,让我突然想起那个百度编辑器UEditor,功能比较齐全而且开源,但也有很多bug和不足。
http://ueditor.baidu.com/website/onlinedemo.html
一年前我就就曾经关注过,让我感到最不能容忍的不足就是,添加的附件的地方,文件和服务器端重名这样的错误如果能够容忍,但如果上传错了,我想删除怎么办呢,居然没有附件管理,如下图所示,字体也太小:
为此我优化了上传,主要是增加增了附件管理,可以删除不需要的附件,效果如下:
上传文件增加了文件类型,和重名判断
附件管理部分,不仅可以显示服务器端的不同附件,而且双击附件可以删除附件。
首先在ueditor\server\submit\net目录下,这里以.net为例,添加一个服务器端文件fileManager.ashx,用来显示服务器端的附件内容,以及删除附件操作代码,前端页面通过AJAX来调用这个文件。
/**
* User: xuhk
* Date: 13-3-15
* 对已经上传的附件进行管理,显示附件,删除附件
*/
using System;
using System.Web;
using System.IO;
public class imageManager : IHttpHandler {
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/plain";
string path = context.Server.MapPath("../../upload/uploadfiles");
string[] filetype = { ".rar", ".doc", ".docx", ".zip", ".pdf", ".txt", ".swf", ".wmv" }; //文件允许格式
string action = context.Server.HtmlEncode(context.Request["action"]);
if(action == "get")
{
String str=String.Empty;
DirectoryInfo info = new DirectoryInfo(path);
//目录验证
if (info.Exists)
{
foreach (FileInfo fi in info.GetFiles())
{
if (Array.IndexOf(filetype, fi.Extension) != -1)
{
str += "uploadfiles/" + fi.Name + "ue_separate_ue";
}
}
}
context.Response.Write(str);
}
//删除选中的文件
string fileName = context.Server.HtmlEncode(context.Request["fileName"]);
if (action == "del")
{
try
{
String fullPath = String.Empty;
fullPath = path + "/" + fileName;
File.Delete(fullPath);
context.Response.Write("success");
}
catch
{
context.Response.Write("error");
}
}
}
public bool IsReusable {
get {
return false;
}
}
}
目录ueditor\dialogs\attachment下的文件attachment.html改为如下形式:
/p>
"http://www.w3.org/TR/html4/loose.dtd">
附件上传附件上传 文件管理
本次共成功上传 0 个文件
文件加载中……
var g = $G,
ajax = parent.baidu.editor.ajax;
/**
* 找到id下具有focus类的节点并返回该节点下的某个属性
* @param id
* @param returnProperty
*/
function findFocus(id, returnProperty) {
var tabs = g(id).children,
property;
for (var i = 0, ci; ci = tabs[i++]; ) {
if (ci.className == "focus") {
property = ci.getAttribute(returnProperty);
break;
}
}
return property;
}
/**
* 绑定确认按钮
*/
function addOKListener() {
dialog.onok = function() {
var currentTab = findFocus("tabHeads", "tabSrc");
switch (currentTab) {
case "file":
return insertBatch();
break;
case "fileManager":
insertSearch("fileListView");
return;
break;
default:
return;
}
}
}
//插入单个文件
function insertBatch() {
var map = fileTypeMaps,
str = "";
for (var i = 0, ci; ci = filesList[i++]; ) {
var src = editor.options.UEDITOR_HOME_URL + "dialogs/attachment/fileTypeImages/" + (map[ci.type] || "icon_default.png");
str += "
" +
"
";}
editor.execCommand("insertHTML", str);
swfupload.destroy();
}
//插入多个文件
function insertSearch(id) {
var fileTypeImg = $G("fileListView").getElementsByTagName("img");
var fileAddress = $G("fileListAddress").getElementsByTagName("a");
for (var i = 0, ci; ci = fileTypeImg[i++]; ) {
if (ci.getAttribute("selected")) {
//i被加1了,所以这里减一
var ci2 = fileAddress[i - 1];
//地址
var url = ci2.getAttribute("src").replace(/(\s*$)/g, "");
//文件名
var arrTitle = url.split("/");
var strTitle = arrTitle[arrTitle.length - 1];
//文件类型
var arrType = url.split(".");
var strType = "." + arrType[arrType.length - 1];
filesList.push({ title: strTitle, url: url, type: strType });
}
}
insertBatch()
}
/**
* 延迟加载
*/
function addScrollListener() {
g("fileListView").onscroll = function() {
var fileTypeImg = this.getElementsByTagName("img"),
top = Math.ceil(this.scrollTop / 100) - 1;
top = top < 0 ? 0 : top;
for (var i = top * 5; i < (top + 5) * 5; i++) {
var img = fileTypeImg[i];
if (img && !img.getAttribute("src")) {
img.src = img.getAttribute("lazy_src");
img.removeAttribute("lazy_src");
}
}
}
}
/**
* 附件缩放
* @param img
* @param max
*/
function scale(img, max, oWidth, oHeight) {
var width = 0, height = 0, percent, ow = img.width || oWidth, oh = img.height || oHeight;
if (ow > max || oh > max) {
if (ow >= oh) {
if (width = ow - max) {
percent = (width / ow).toFixed(2);
img.height = oh - oh * percent;
img.width = max;
}
} else {
if (height = oh - max) {
percent = (height / oh).toFixed(2);
img.width = ow - ow * percent;
img.height = max;
}
}
}
}
function selectTxt(node) {
if (node.select) {
node.select();
} else {
var r = node.createTextRange && node.createTextRange();
r.select();
}
}
/**
* 改变o的选中状态
* @param o
*/
function changeSelected(o) {
if (o.getAttribute("selected")) {
o.removeAttribute("selected");
o.childNodes[0].removeAttribute("selected");
o.style.cssText = "filter:alpha(Opacity=100);-moz-opacity:1;opacity: 1;border: 1px solid #E8E8E8;";
/*为选中文件下部的文件名DIV部分增加样式*/
o.childNodes[1].style.cssText = "filter:alpha(Opacity=100);-moz-opacity:1;opacity: 1;border: 0px solid #E8E8E8;";
} else {
o.setAttribute("selected", "true");
o.childNodes[0].setAttribute("selected", "true");
o.style.cssText = "filter:alpha(Opacity=100);-moz-opacity:0.5;opacity: 0.5;border:1px solid #316ac5;background-color: #F0F5FF;";
/*为选中文件下部的文件名DIV部分增加样式*/
o.childNodes[1].style.cssText = "filter:alpha(Opacity=100);-moz-opacity:0.5;opacity: 0.5;border:0px solid #316ac5;background-color: #F0F5FF;";
}
}
/**
* tab切换
* @param tabParentId
* @param keepFocus 当此值为真时,切换按钮上会保留focus的样式
*/
function switchTab(tabParentId, keepFocus) {
var tabElements = $G(tabParentId).children,
tabHeads = tabElements[0].children,
tabBodys = tabElements[1].children;
var map = fileTypeMaps;
for (var i = 0, length = tabHeads.length; i < length; i++) {
var head = tabHeads[i];
domUtils.on(head, "click", function() {
//head样式更改
for (var k = 0, len = tabHeads.length; k < len; k++) {
if (!keepFocus) tabHeads[k].className = "";
}
this.className = "focus";
//body显隐
var tabSrc = this.getAttribute("tabSrc");
for (var j = 0, length = tabBodys.length; j < length; j++) {
var body = tabBodys[j],
id = body.getAttribute("id");
if (id == tabSrc) {
body.style.display = "";
if (id == "fileManager") {
//转换到文件管理TAB时,显示DIV里的内容
g("fileManager").style.display = "";
g("fileListView").style.display = "";
var list = g("fileListView");
//已经初始化过时不再重复提交请求
//2013-03-09删除这个判断,这样才能保证上传新文件后,点管理附件显示新的附件你
// if (!list.children.length) {
ajax.request(editor.options.fileManagerPath, {
timeout: 100000,
action: "get",
onsuccess: function(xhr) {
var tmp = xhr.responseText,
imageUrls = !tmp ? [] : tmp.split("ue_separate_ue"),
length = imageUrls.length;
//当服务器没上传文件的时候
if (0 == length) {
g("fileManager").style.display = "";
list.style.display = "";
list.innerHTML = !length ? " 当前未上传过任何附件!" : "";
} else {
list.innerHTML = "";
}
for (var i = 0, ci; ci = imageUrls[i++]; ) {
//文件真实地址
var url = editor.options.UEDITOR_HOME_URL + ci;
//创建一个图片标签来显示文件类型图标
var img = document.createElement("img");
//创建一个链接标签来存放文件真实地址
var a = document.createElement("a");
//显示单个文件信息的DIV快
var divFileView = document.createElement("div");
//存放单个文件地址
var divFileAddress = document.createElement("div");
//在文件类型图标上,增加个fileAddress属性,存放该文件的真实地址,目的为了双击图标删除此文件
divFileView.setAttribute("fileAddress", url);
divFileView.appendChild(img);
// 在显示文件类型图标下显示文件名
var divFileName = document.createElement("div");
var arrFileName = ci.split("/");
var strFileName = arrFileName[arrFileName.length - 1];
//在鼠标放上面给出全文件名提示
img.parentNode.title = strFileName
//获得文件扩展名前点的位置,并去掉文件扩展名
var indexDot = strFileName.lastIndexOf(".");
strFileName = strFileName.substring(0, indexDot);
//文件名太长就截取
if (strFileName.length >= 6)
strFileName = strFileName.substring(0, 6);
//把文件名显示在图标下面
divFileName.innerHTML = strFileName;
divFileView.appendChild(divFileName);
divFileAddress.appendChild(a);
//显示文件类型
g("fileListView").appendChild(divFileView);
//隐藏DIV,对应显示文件的真实地址
g("fileListAddress").appendChild(divFileAddress);
//单击选中
img.parentNode.onclick = function() {
changeSelected(this);
};
//双击删除
img.parentNode.ondblclick = function() {
var me = this,
src = me.getAttribute("fileAddress");
if (!confirm("删除操作不可恢复,您确认要删除本附件么?")) return;
ajax.request(editor.options.fileManagerPath, {
action: "del",
fileName: src.substr(src.lastIndexOf("/") + 1),
onsuccess: function(xhr) {
if (xhr.responseText == "success") {
me.parentNode.removeChild(me);
} else {
alert("服务器删除附件失败,请重试!");
}
}
});
};
img.onload = function() {
this.parentNode.style.display = "";
var w = this.width, h = this.height;
scale(this, 100, 200, 80);
};
//文件类型图标地址
var arrType = url.split(".");
var strType = "." + arrType[arrType.length - 1];
var imgTypeURL = editor.options.UEDITOR_HOME_URL + "dialogs/attachment/fileTypeImages/" + map[strType];
img.setAttribute(i < 35 ? "src" : "lazy_src", imgTypeURL);
img.setAttribute("data_ue_src", imgTypeURL);
//文件存放真实地址
a.setAttribute(i < 35 ? "src" : "lazy_src", ci);
a.setAttribute("data_ue_src", ci);
list.style.display = "";
}
},
onerror: function() {
g("fileListView").innerHTML = "糟糕,附件读取失败了!";
}
});
// }
}
//当切换到本地附件上传时,隐藏遮罩用的iframe
if (id == "file") {
g("fileManager").style.display = "none";
g("fileListView").style.display = "none";
}
}
else {
body.style.display = "none";
}
}
});
}
}
var swfupload,
filesList = [];
window.onload = function() {
var settings = {
flash_url: "../../third-party/swfupload/swfupload.swf",
flash9_url: "../../third-party/swfupload/swfupload_fp9.swf",
upload_url: "../../server/upload/net/fileUp.ashx", //附件上传服务器地址
post_params: { "PHPSESSID": "<?php echo session_id(); ?>" }, //解决session丢失问题
file_size_limit: "100 MB", //文件大小限制,此处仅是前端flash选择时候的限制,具体还需要和后端结合判断
file_types: "*.*", //允许的扩展名,多个扩展名之间用分号隔开,支持*通配符
file_types_description: "All Files", //扩展名描述
file_upload_limit: 100, //单次可同时上传的文件数目
file_queue_limit: 10, //队列中可同时上传的文件数目
custom_settings: { //自定义设置,用户可在此向服务器传递自定义变量
progressTarget: "fsUploadProgress",
startUploadId: "startUpload"
},
debug: false,
// 按钮设置
button_image_url: "../../themes/default/images/fileScan.png",
button_width: "100",
button_height: "25",
button_placeholder_id: "spanButtonPlaceHolder",
button_text: '文件浏览…',
button_text_style: ".theFont { font-size:14px;}",
button_text_left_padding: 10,
button_text_top_padding: 4,
// 所有回调函数 in handlers.js
swfupload_preload_handler: preLoad,
swfupload_load_failed_handler: loadFailed,
file_queued_handler: fileQueued,
file_queue_error_handler: fileQueueError,
//选择文件完成回调
file_dialog_complete_handler: function(numFilesSelected, numFilesQueued) {
var me = this; //此处的this是swfupload对象
if (numFilesQueued > 0) {
dialog.buttons[0].setDisabled(true);
var start = $G(this.customSettings.startUploadId);
start.style.display = "";
start.onclick = function() {
me.startUpload();
start.style.display = "none";
}
}
},
upload_start_handler: uploadStart,
upload_progress_handler: uploadProgress,
upload_error_handler: uploadError,
upload_success_handler: function(file, serverData) {
try {
var info = eval("(" + serverData + ")");
} catch (e) { }
var progress = new FileProgress(file, this.customSettings.progressTarget);
if (info.state == "SUCCESS") {
progress.setComplete();
progress.setStatus("上传成功!");
//filesList.push({ url: info.url, type: info.fileType});
filesList.push({ title: info.title, url: info.url, type: info.fileType });
progress.toggleCancel(true, this, "从成功队列中移除");
} else {
progress.setError();
progress.setStatus(info.state);
progress.toggleCancel(true, this, "移除保存失败文件");
}
},
//上传完成回调
upload_complete_handler: uploadComplete,
//队列完成回调
queue_complete_handler: function(numFilesUploaded) {
dialog.buttons[0].setDisabled(false);
var status = $G("divStatus");
var num = status.innerHTML.match(/\d+/g);
status.innerHTML = "本次共成功上传 " + ((num && num[0] ? parseInt(num[0]) : 0) + numFilesUploaded) + " 个文件";
}
};
swfupload = new SWFUpload(settings);
dialog.oncancel = function() {
swfupload.destroy();
}
switchTab("fileTab");
addOKListener();
addScrollListener();
};
转载地址:http://amcup.baihongyu.com/