立即注册 登录
彼岸网 返回首页

天香公主的个人空间 http://www.bian-wang.com/discuz/?10005 [收藏] [复制] [分享] [RSS] txgz999@yahoo.com

日志

Discuz功能改进:将论坛里的文件上传对iPad的支持扩展到日志文章和相册 ...

热度 6已有 2973 次阅读2015-7-16 11:37 PM |个人分类:Discuz| 文章

过去我曾经分析过日志里的图片上传机制 (链接),讨论过在那里使用基于Flash的SWFUpload组件的必要性。但没想到论坛里的类似功能提供了基于Flash技术和不基于Flash技术的两套上传方案,按浏览器是否支持Flash来选择用哪套方案。本文分析一下它的机制,并将它扩展到日志,文章和相册里。

首先注意整个发表贴子的网页所用的模板是 forum/post.htm,它引用了 javascript 文件 static/js/forum_post.js。它还嵌入了两个子模板 forum/editor_menu_forum.htm 和 common/upload.htm,而后者引用了 javascript 文件 static/js/upload.js。
post.htm: <script type="text/javascript" src="{$_G['setting']['jspath']}forum_post.js?{VERHASH}"></script> <!--{subtemplate forum/editor_menu_forum}--> <!--{subtemplate common/upload}--> upload.htm: <!--{if empty($_G['uploadjs'])}--> <script type="text/javascript" src="{$_G[setting][jspath]}upload.js?{VERHASH}"></script> {eval $_G['uploadjs'] = 1;} <!--{/if}-->
1。我们先来分析是在哪里选择是否用基于Flash的上传方法的: 下面是在Firefox里的图片上传界面截屏,第一张是在Add-ons Manager激活了Shockwave Flash 的情形,第二张是不激活的情形:

从中可见,在这两种情形下,出现的是同一个弹出窗口,但所用的TAB不同。这四个TAB (上传图片,普通上传,相册图片,网络图片)定义在editor_menu_forum.htm 里:

<ul class="tb tb_s cl" id="{$editorid}_image_ctrl" style="margin-top:0;margin-bottom:0;"> <li class="y"><span class="flbc" onclick="hideAttachMenu('image')">{lang close}</span></li> <!--{if $allowpostimg}--> <li class="current" id="{$editorid}_btn_imgattachlist">< a href="javascript:;" hidefocus="true" onclick="switchImagebutton('imgattachlist');">{lang e_img_attach}</a></li> <!--{if $allowuploadtoday}--> <li id="{$editorid}_btn_local" style="display:none;" did="{$editorid}_btn_imgattachlist|local">< a href="javascript:;" hidefocus="true" onclick="switchImagebutton('local');">{lang normal_upload}</a></li> <!--{/if}--> <!--{/if}--> <!--{if helper_access::check_module('album')}--> <li {if !$allowpostimg}class="current"{/if} id="{$editorid}_btn_albumlist">< a href="javascript:;" hidefocus="true" onclick="switchImagebutton('albumlist');">{lang e_img_albumlist}</a></li> <!--{/if}--> <li {if !$allowpostimg && !helper_access::check_module('album')}class="current"{/if} id="{$editorid}_btn_www">< a href="javascript:;" hidefocus="true" onclick="switchImagebutton('www');">{lang e_img_www}</a></li> <!--{hook/post_image_btn_extra}--> </ul> 注意在定义普通上传TAB时用的属性 did="{$editorid}_btn_imgattachlist|local",这个信息告诉下面的代码上传图片TAB和普通上传TAB会有一个被隐藏:
upload.js: function disableMultiUpload(obj) { if(obj.uploadSource == 'forum' && obj.uploadFrom != 'fastpost') { try{ obj.singleUpload.style.display = ''; var dIdStr = obj.singleUpload.getAttribute("did"); if(dIdStr != null) { if(typeof forum_post_inited == 'undefined') { appendscript(JSPATH + 'forum_post.js?' + VERHASH); } var idArr = dIdStr.split("|"); $(idArr[0]).style.display = 'none'; if(idArr[1] == 'local') { switchImagebutton('local'); } else if(idArr[1] == 'upload') { switchAttachbutton('upload'); } } } catch (e) { } } } function preLoad() { if(!this.support.loading) { disableMultiUpload(this.customSettings); return false; } } function loadFailed() { disableMultiUpload(this.customSettings); } var SWFUpload; var swfobject; if (SWFUpload == undefined) { SWFUpload = function (settings) { this.initSWFUpload(settings); }; } SWFUpload.prototype.initSWFUpload = function (userSettings) { ... this.loadSupport(); ... } SWFUpload.prototype.loadSupport = function () { this.support = { loading : swfobject.hasFlashPlayerVersion("9.0.28"), imageResize : false }; }; post.htm: var imgUpload = new SWFUpload({ ... swfupload_preload_handler : preLoad, swfupload_load_failed_handler : loadFailed, ...

SWFUpload 定义在 upload.js 里,它在处理 preload 事件会检查浏览器是否支持 Flash。如果不支持就会调用 disableMultiUpload 来隐藏图片上传TAB而显示普通上传TAB。同时它需要用到Flash。所以当浏览器里的Flash没有被激活时,它的 load_failed 事件处理代码就会被调用,它同样会调用 disableMultiUpload。

2。接下来我们来分析一下不用Flash时的选择文件的代码:

上传图片列表和上传按钮定义在文件 editor_menu_forum.htm 里:
<table cellpadding="0" cellspacing="0" border="0" width="100%"> <tbody id="imgattachbodyhidden" style="display:none"><tr> <td class="atnu"><span id="imglocalno[]"><img src="{STATICURL}image/filetype/common_new.gif" /></span></td> <td class="atna"> <span id="imgdeschidden[]" style="display:none"> <span id="imglocalfile[]"></span> </span> <input type="hidden" name="imglocalid[]" /> </td> <td class="attc"><span id="imgcpdel[]"></span></td> </tr></tbody> </table> <div class="p_tbl"><table cellpadding="0" cellspacing="0" summary="post_attachbody" border="0" width="100%"><tbody id="imgattachbody"></tbody></table></div> <div class="upbk pbm bbda"> <div id="imgattachbtnhidden" style="display:none"><span> <form name="imgattachform" id="imgattachform" method="post" autocomplete="off" action="misc.php?mod=swfupload&operation=upload&simple=1&type=image" target="attachframe" $enctype> <input type="hidden" name="uid" value="$_G['uid']"> <input type="hidden" name="hash" value="{echo md5(substr(md5($_G['config']['security']['authkey']), 8).$_G['uid'])}"> <input type="file" name="Filedata" size="45" class="filedata" /></form></span></div> <div id="imgattachbtn" class="ptm pbn"></div>
上传文件列表是 imgattachbody,它的内容是以 imgattachbodyhidden 为模版生成的。还有一个上传表单(form)列表 imgattachbtn,它的内容是以 imgattachbtnhidden 为模版生成的。接下来的代码显示了它们的生成过程。 当用户选择了一个文件后,界面上的上传文件列表会更新,上传表单列表也会更新,这是由这个选择文件按钮的 change 事件处理代码提供的功能: 注意下面的语句调用了一个按模版产生选择文件表单的函数,其中对选择文件按钮加了事件处理来达到前述效果。
post.htm: <!--{if $allowpostimg}-->addAttach('img');<!--{/if}--> forum_post.js: function addAttach(prefix) { var id = AID[prefix ? 1 : 0]; var tags, newnode, i; prefix = isUndefined(prefix) ? '' : prefix; newnode = $(prefix + 'attachbtnhidden').firstChild.cloneNode(true); tags = newnode.getElementsByTagName('input'); for(i = 0;i < tags.length;i++) { if(tags[i].name == 'Filedata') { tags[i].id = prefix + 'attachnew_' + id; tags[i].onchange = function() {insertAttach(prefix, id);}; tags[i].unselectable = 'on'; } else if(tags[i].name == 'attachid') { tags[i].value = id; } } tags = newnode.getElementsByTagName('form'); tags[0].name = tags[0].id = prefix + 'attachform_' + id; $(prefix + 'attachbtn').appendChild(newnode); newnode = $(prefix + 'attachbodyhidden').firstChild.cloneNode(true); tags = newnode.getElementsByTagName('input'); for(i = 0;i < tags.length;i++) { if(tags[i].name == prefix + 'localid[]') { tags[i].value = id; } } tags = newnode.getElementsByTagName('span'); for(i = 0;i < tags.length;i++) { if(tags[i].id == prefix + 'localfile[]') { tags[i].id = prefix + 'localfile_' + id; } else if(tags[i].id == prefix + 'cpdel[]') { tags[i].id = prefix + 'cpdel_' + id; } else if(tags[i].id == prefix + 'localno[]') { tags[i].id = prefix + 'localno_' + id; } else if(tags[i].id == prefix + 'deschidden[]') { tags[i].id = prefix + 'deschidden_' + id; } } AID[prefix ? 1 : 0]++; newnode.style.display = 'none'; $(prefix + 'attachbody').appendChild(newnode); } function insertAttach(prefix, id) { var path = $(prefix + 'attachnew_' + id).value; var extpos = path.lastIndexOf('.'); var ext = extpos == -1 ? '' : path.substr(extpos + 1, path.length).toLowerCase(); var re = new RegExp("(^|\\s|,)" + ext + "($|\\s|,)", "ig"); var localfile = $(prefix + 'attachnew_' + id).value.substr($(prefix + 'attachnew_' + id).value.replace(/\\/g, '/').lastIndexOf('/') + 1); var filename = mb_cutstr(localfile, 30); if(path == '') { return; } if(extensions != '' && (re.exec(extensions) == null || ext == '')) { reAddAttach(prefix, id); showError('对不起,不支持上传此类扩展名的附件。'); return; } if(prefix == 'img' && imgexts.indexOf(ext) == -1) { reAddAttach(prefix, id); showError('请选择图片文件(' + imgexts + ')'); return; } $(prefix + 'cpdel_' + id).innerHTML = '< a href="javascript:;" class="d" onclick="reAddAttach(\'' + prefix + '\', ' + id + ')">删除</a>'; $(prefix + 'localfile_' + id).innerHTML = '<span>' + filename + '</span>'; $(prefix + 'attachnew_' + id).style.display = 'none'; $(prefix + 'deschidden_' + id).style.display = ''; $(prefix + 'deschidden_' + id).title = localfile; $(prefix + 'localno_' + id).parentNode.parentNode.style.display = ''; addAttach(prefix); UPLOADSTATUS = 0; } 上传按钮的值(value)只有在IE里才记录了所选文件的路径和文件名,在Firefox和Chrome里出于安全考虑都只记录了文件名。

3。接下来我们来分析一下不用Flash时的上传文件的代码。 上传按钮定义在接下来的代码里: <p id="imguploadbtn"> <button class="pn pnc vm" type="button" onclick="uploadAttach(0, 0, 'img')"><span>{lang upload}</span></button> <span class="xg1">&larr;{lang upload_after_selected}</span> </p> <p id="imguploading" style="display: none;"><img src="{IMGDIR}/uploading.gif" style="vertical-align: middle;" /> {lang uploading}</p> 当用户点击上传按钮后,处理 onclick 事件的代码调用了定义在 forum_post.js 里的函数 uploadAttach: function uploadAttach(curId, statusid, prefix, sizelimit) { prefix = isUndefined(prefix) ? '' : prefix; var nextId = 0; for(var i = 0; i < AID[prefix ? 1 : 0] - 1; i++) { if($(prefix + 'attachform_' + i)) { nextId = i; if(curId == 0) { break; } else { ... $(prefix + 'attachform_' + nextId).submit(); } 注意这个函数的结尾处将该表单 (form) 提交给了服务器。但是用户在这个网页上可能已经选择了多个图片,每个选择对应着一个上传表单。如何将每个表单里选择的图片都提交给服务器呢?注意表单的 target 属性的值是 attachframe ,对应着定义在 editor_menu_forum.htm 里的下述 iframe: <iframe name="attachframe" id="attachframe" style="display: none;" onload="uploadNextAttach();"></iframe> 所以图片提交后会调用定义在 forum_post.js 里的函数 uploadNextAttach: function uploadNextAttach() { var str = $('attachframe').contentWindow.document.body.innerHTML; if(str == '') return; var arr = str.split('|'); var att = CURRENTATTACH.split('|'); var sizelimit = ''; if(arr[4] == 'ban') { sizelimit = '(附件类型被禁止)'; } else if(arr[4] == 'perday') { sizelimit = '(不能超过 ' + arr[5] + ' 字节)'; } else if(arr[4] > 0) { sizelimit = '(不能超过 ' + arr[4] + ' 字节)'; } uploadAttach(parseInt(att[0]), arr[0] == 'DISCUZUPLOAD' ? parseInt(arr[1]) : -1, att[1], sizelimit); } 而在它的结尾处又调用了uploadAttach,周而复始,从而将所有选择的图片都上传到服务器了。

4。那么论坛里不用Flash的上传文件方法能不能用于日志(以及文章)呢?我们先对照一下两者用到的相关代码文件结构:
forum_post.php
    defines $editorid = 'e'
    includes post_newthread.php/post_newreply.php/post_editpost.php
        template post.htm
            includes forum_post.js
                defines addAttach
            subtemplate post_editor_body.htm
                subtemplate editor.htm
                    defines editorid = '$editorid';
            subtemplate editor_menu_forum.htm
                defines switchImagebutton 
            subtemplate upload.htm
                includes upload.js
                    defines SWFUpload class
            creates SWFUpload object
            calls addAttach('img')

home_spacecp.php
    includes spacecp_blog.php    
        template spacecp_blog.htm
            includes editor_function.js
            subtemplate editor_image_menu.htm
                subtemplate upload.htm
                    includes upload.js
                        defines SWFUpload class
                creates SWFUpload object
                defines switchImagebutton
大致上说 editor_image_menu.htm 和 editor_menu_forum.htm 对应定义了上传文件的对话框的内容,而 editor_function.js 和 forum_post.js 对应定义了上传文件的对话框的在客户端的功能。这两个是我们要重点修改的文件。

我们先做些辅助性的改动:
1) 文件 static/js/upload.js 里的函数 disableMultiUpload 引发了在支持和不支持Flash时在上传文件对话框里选择显示合适的TAB。我们要加入对日志和文章的支持。将下面的代码 function disableMultiUpload(obj) { if(obj.uploadSource == 'forum' && obj.uploadFrom != 'fastpost') { try{ obj.singleUpload.style.display = ''; var dIdStr = obj.singleUpload.getAttribute("did"); if(dIdStr != null) { if(typeof forum_post_inited == 'undefined') { appendscript(JSPATH + 'forum_post.js?' + VERHASH); } 修改为 function disableMultiUpload(obj) { if ((obj.uploadSource == 'portal' || obj.uploadSource == 'forum') && obj.uploadFrom != 'fastpost') { try { obj.singleUpload.style.display = ''; var dIdStr = obj.singleUpload.getAttribute("did"); if (dIdStr != null) { if (obj.uploadSource == 'forum') { if (typeof forum_post_inited == 'undefined') { appendscript(JSPATH + 'forum_post.js?' + VERHASH); } } 2) 接下来在文件 static/image/editor/editor_function.js 里加入下面的函数来支持上传文件的功能: function uploadFile(prefix) { prefix = isUndefined(prefix) ? '' : prefix; var path = $(prefix + 'attachnew').value; var extpos = path.lastIndexOf('.'); var ext = extpos == -1 ? '' : path.substr(extpos + 1, path.length).toLowerCase(); var re = new RegExp("(^|\\s|,)" + ext + "($|\\s|,)", "ig"); var localfile = $(prefix + 'attachnew').value.substr($(prefix + 'attachnew').value.replace(/\\/g, '/').lastIndexOf('/') + 1); var filename = mb_cutstr(localfile, 30); if (path == '') { return; } if (extensions != '' && (re.exec(extensions) == null || ext == '')) { showError('对不起,不支持上传此类扩展名的附件。'); return; } if (prefix == 'img' && imgexts.indexOf(ext) == -1) { showError('请选择图片文件(' + imgexts + ')'); return; } var form = $(prefix + 'attachnew').form; if ($('formaction')) { $('formaction').value = form.action; form.action = $('localformaction').value; form.target = (prefix == 'img') ? 'imageframe' : 'attachframe'; if (prefix != 'img') $('imgattachnew').name = ''; if (prefix != '') $('attachnew').name = ''; } form.submit(); } function uploadImageDone() { if ($('formaction').value) { $('formaction').form.action = $('formaction').value; $('formaction').form.target = ""; $('imgattachnew').name = 'Filedata'; $('attachnew').name = 'Filedata'; } var str = $('imageframe').contentWindow.document.body.innerHTML; if (str == '') return; var data = eval('(' + str + ')'); if (parseInt(data.picid)) { var tdObj = getInsertTdId($('imgattachlist'), 'image_td_' + data.picid); var img = new Image(); img.src = data.url; var imgObj = document.createElement("img"); imgObj.src = img.src; imgObj.className = "cur1"; imgObj.onclick = function () { insertImage(data.bigimg); }; tdObj.appendChild(imgObj); var inputObj = document.createElement("input"); inputObj.type = 'hidden'; inputObj.name = 'picids[' + data.picid + ']'; inputObj.value = data.picid; tdObj.appendChild(inputObj); } else if (data.aid) { var tdObj = getInsertTdId($('imgattachlist'), 'attach_list_' + data.aid); ajaxget('portal.php?mod=attachment&op=getattach&id=' + data.aid, tdObj.id); } else { showDialog('图片上传失败', 'notice', null, null, 0, null, null, null, null, sdCloseTime); } } function uploadAttachmentDone() { if ($('formaction').value) { $('formaction').form.action = $('formaction').value; $('formaction').form.target = ""; $('imgattachnew').name = 'Filedata'; $('attachnew').name = 'Filedata'; } var str = $('attachframe').contentWindow.document.body.innerHTML; if (str == '') return; var data = eval('(' + str + ')'); if (data.aid) { var tdObj = $('attachlist'); var fileObj = document.createElement("div"); fileObj.id = 'FileUpload_' + tdObj.childNodes.length; tdObj.appendChild(fileObj); ajaxget('portal.php?mod=attachment&op=getattach&type=attach&id=' + data.aid, fileObj.id); if ($('attach_tblheader')) { $('attach_tblheader').style.display = ''; } } else { showDialog('上传失败', 'notice', null, null, 0, null, null, null, null, sdCloseTime); } } 它们效仿了 static/js/forum_post.js 里的函数 uploadAttach 和 uploadNextAttach的框架,而其中后两个函数的代码参照了日志和文章在支持Flash时处理(static/js/upload.js 里的 uploadSuccess 函数)。
再对原有的函数 switchButton 略做改动,使之同时适用于图片上传和附件上传: function switchButton(btn, type) { var pre = 'ico' + ((type == 'attach') ? 'Attach' : 'Img') + '_'; var btnpre = pre + 'btn_'; if (!$(btnpre + btn) || !$(pre + btn)) { return; } var tabs = $(pre + type + '_ctrl').getElementsByTagName('LI'); $(btnpre + btn).style.display = ''; $(pre + btn).style.display = ''; $(btnpre + btn).className = 'current'; var btni = ''; for(i = 0;i < tabs.length;i++) { if(tabs[i].id.indexOf(btnpre) !== -1) { btni = tabs[i].id.substr(btnpre.length); } if(btni != btn) { if (!$(pre + btni) || !$('icoImg_btn_' + btni)) { continue; } $(pre + btni).style.display = 'none'; $(btnpre + btni).className = ''; } } } 3) 最后我们要对修改定义上传文件对话框的模板文件 template/default/home/editor_image_menu.htm 做多处改动:
3a) 在文件的开头加上 <script type="text/javascript"> var extensions = ''; var imgexts = "$swfconfig[imageexts][ext]"; function populateLocalSection(type) { var c = $('icoImg_imgattachlist').innerHTML; if (c) { var sv ='<span id="imgSpanButtonPlaceholder"></span>'; var nv = '<input type="file" name="Filedata" size="45" class="filedata" id="imgattachnew" onchange="uploadFile(\'img\');" />'; $('icoImg_local').innerHTML = c.replace(sv, nv); $('icoImg_imgattachlist').innerHTML = ''; } } function populateUploadSection(type) { var c = $('icoAttach_attachlist').innerHTML; if (c) { var lc = $('icoAttach_upload').innerHTML; var sv ='<span id="spanButtonPlaceholder"></span>'; var nv = '<input type="file" name="Filedata" size="45" class="filedata" id="attachnew" onchange="uploadFile();" />'; $('icoAttach_upload').innerHTML = c.replace(sv, nv); $('icoAttach_attachlist').innerHTML = ''; } } function switchImagebutton(btn) { if (btn == 'local') populateLocalSection(); switchButton(btn, 'image'); $('icoImg_image_menu').style.height = ''; doane(); } function switchAttachbutton(btn) { if (btn == 'upload') populateUploadSection(); switchButton(btn, 'attach'); doane(); } </script> 3b) 在图片对话框里要添加一个TAB,它在没有 Flash 的环境里替代了原来的"上传图片"TAB。先添加新TAB的标题: 在下面这句 <li class="current" id="icoImg_btn_imgattachlist"><a href="javascript:;" hidefocus="true" onclick="switchImagebutton('imgattachlist');" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank">{lang upload_pic}</a></li> 后加上 <li id="icoImg_btn_local" style="display:none;" did="icoImg_btn_imgattachlist|local"><a href="javascript:;" hidefocus="true" onclick="switchImagebutton('local');" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank">{lang upload_pic}</a></li> 再添加新TAB的内容: 在下面这句 <div class="p_opt" unselectable="on" id="icoImg_imgattachlist"{if $_G['basescript'] == 'home' && !$_G['group']['allowupload']} style="display: none;"{/if}> 前加上 <div class="p_opt" unselectable="on" id="icoImg_local" style="display: none;"></div> 3c) 对文章里的附件上传要做类似的改动: 在下面这句 <li class="current" id="icoAttach_btn_attachlist"><a href="javascript:;" hidefocus="true" onclick="switchAttachbutton('attachlist');" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank">{lang upload_attach}</a></li> 后加上 <li id="icoAttach_btn_upload" style="display: none;" did="icoAttach_btn_attachlist|upload"><a href="javascript:;" hidefocus="true" onclick="switchAttachbutton('upload');" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank" target="_blank">{lang upload_attach}</a></li> 在下面这句 <div class="p_opt post_tablelist" unselectable="on" id="icoAttach_attachlist"> 前加上 <div class="p_opt post_tablelist" unselectable="on" id="icoAttach_upload" style="display: none;"></div> 3d) 还要加些支持上传的内容: 将下面这句 <iframe name="attachframe" id="attachframe" style="display: none;"></iframe> 改为: <input type="hidden" name="uid" value="$_G['uid']"> <input type="hidden" name="hash" value="$swfconfig[hash]"> <input type="hidden" id="formaction" value="" /> <input type="hidden" id="localformaction" value="misc.php?mod=swfupload&operation=<!--{if $_G['basescript'] == 'portal'}-->portal<!--{else}-->album<!--{/if}-->" /> <iframe name="imageframe" id="imageframe" style="display: none;" onload="uploadImageDone();"></iframe> <iframe name="attachframe" id="attachframe" style="display: none;" onload="uploadAttachmentDone();"></iframe> 3e) 还要告诉SWFUpload的两个实例如何处理不支持 Flash 的情形。将下面这句 imgBoxObj: $('attachlist') 改为 imgBoxObj: $('attachlist'), singleUpload: $('icoAttach_btn_upload') 将下面这句 imgBoxObj: $('imgattachlist') 改为 imgBoxObj: $('imgattachlist'), singleUpload: $('icoImg_btn_local') 3f) 最后将该文件后面的函数 switchImagebutton 的定义删掉: function switchImagebutton(btn) { switchButton(btn, 'image'); $('icoImg_image_menu').style.height = ''; doane(); } 这些修改借鉴了template/default/forum/editor_menu_forum.htm 里的代码。

5。最后我们讨论一下在相册里不用Flash的上传图片方法。

首先将 static/js/upload.js 里的函数 disableMultiUpload 的第一行 if ((obj.uploadSource == 'portal' || obj.uploadSource == 'forum') && obj.uploadFrom != 'fastpost') { 改为 if ((obj.uploadSource == 'home' || obj.uploadSource == 'portal' || obj.uploadSource == 'forum') && obj.uploadFrom != 'fastpost') { 其次在文件 static/image/editor/editor_function.js 里再添加一个辅助函数来支持在相册里上传图片的功能: function uploadToAlbumDone() { var str = $('imageframe').contentWindow.document.body.innerHTML; if (str == '') return; var data = eval('(' + str + ')'); if (parseInt(data.picid)) { var newTr = document.createElement("TR"); var newTd = document.createElement("TD"); var img = new Image(); img.src = data.url; var imgObj = document.createElement("img"); imgObj.src = img.src; newTd.className = 'c'; newTd.appendChild(imgObj); newTr.appendChild(newTd); newTd = document.createElement("TD"); var localfile = $('imgattachnew').value.substr($('imgattachnew').value.replace(/\\/g, '/').lastIndexOf('/') + 1); var filename = mb_cutstr(localfile, 30); newTd.innerHTML = '<strong>' + filename + '</strong>'; newTr.appendChild(newTd); newTd = document.createElement("TD"); newTd.className = 'd'; newTd.innerHTML = '图片描述<br/><textarea name="title[' + data.picid + ']" cols="40" rows="2" class="pt"></textarea>'; newTr.appendChild(newTd); $('attachbody').appendChild(newTr); } else { showDialog('图片上传失败', 'notice', null, null, 0, null, null, null, null, sdCloseTime); } } 和前面提到的函数类似,这个函数也是模仿了static/js/upload.js 里的 uploadSuccess 函数中的相关部分。

最后我们要修改定义相册上传图片网页的模板文件 template/default/home/spacecp_upload.htm。要做下面五部分的修改:
1)在第一行 <!--{template common/header}--> 的下面插入: <script type="text/javascript" src="{STATICURL}image/editor/editor_function.js?{VERHASH}"></script> <script type="text/javascript"> var extensions = ''; var imgexts = "$swfconfig[imageexts][ext]"; function switchImagebutton(btn) { switchButton(btn, 'image'); doane(); } </script> 2)要加上一个在不支持Flash情形下显示的TAB,所以要加一个LI,还有给已有的元素也加上ID。找到下面这段: <ul class="tb cl"> <!--{if $albumid}--> <li>< a href="home.php?mod=spacecp&ac=album&op=edit&albumid=$albumid" target="_blank">{lang edit_album_information}</a></li> <li>< a href="home.php?mod=spacecp&ac=album&op=editpic&albumid=$albumid" target="_blank">{lang edit_pic}</a></li> <!--{/if}--> <li$actives[js] >< a href="home.php?mod=spacecp&ac=upload&albumid=$albumid" target="_blank">{lang common_upload}</a></li> 将它改为 <ul class="tb cl" id="icoImg_image_ctrl"> <!--{if $albumid}--> <li>< a href="home.php?mod=spacecp&ac=album&op=edit&albumid=$albumid" target="_blank">{lang edit_album_information}</a></li> <li>< a href="home.php?mod=spacecp&ac=album&op=editpic&albumid=$albumid" target="_blank">{lang edit_pic}</a></li> <!--{/if}--> <li$actives[js] id="icoImg_btn_album">< a href="home.php?mod=spacecp&ac=upload&albumid=$albumid" target="_blank">{lang common_upload}</a></li> <li id="icoImg_btn_local" style="display:none;" did="icoImg_btn_album|local">< a href="javascript:;" hidefocus="true" onclick="switchImagebutton('local');">{lang common_upload}</a></li> 3)我们要将现有的表单的范围缩小一点,使得新加的上传图片的表单与它没有重叠之处。找到 <form method="post" autocomplete="off" id="albumform" action="home.php?mod=spacecp&ac=upload" onsubmit="return validate(this);"> 将它搬到它下面两句 <h2 class="mtw xs2">1. {lang select_pic}</h2> <div class="xg1">{lang upload_pic_tips}</div> 的下面。
4)现在添加在不支持Flash情形下的图片选择和上传按钮。在3)中提到的表单句的上面插入 <div class="p_opt" unselectable="on" id="icoImg_album"></div> <div unselectable="on" id="icoImg_local" style="display: none;"> <div class="upbk pbm bbda"> <div id="imgattachbtn" class="ptm pbn"> <form name="imgattachform" id="imgattachform" method="post" autocomplete="off" action="misc.php?mod=swfupload&action=swfupload&operation=album" target="imageframe" enctype="multipart/form-data"> <input type="hidden" name="uid" value="$_G['uid']"> <input type="hidden" name="hash" value="$swfconfig['hash']"> <input type="file" name="Filedata" size="45" class="filedata" id="imgattachnew" onchange="uploadFile('img');" /> </form> </div> <p id="imguploading_local" style="display: none;"><img src="{IMGDIR}/uploading.gif" style="vertical-align: middle;" /> {lang uploading}</p> </div> </div> <iframe name="imageframe" id="imageframe" style="display: none;" onload="uploadToAlbumDone();"></iframe> 5)在生成SWFUpload对象的语句里找到下面一行 imgBoxObj: $('attachbody') 将它换成: imgBoxObj: $('attachbody'), singleUpload: $('icoImg_btn_local') 下面是效果图:



注:本文中的代码里的<符号如果后面的字符是a的话,在它们中间加了一个不应该有的空格,以避免Discuz在保存日志时自动改变日志内容。

05/27/2016补充: 更新了本文的内容和文末的下载文件,改正了原文中的一个问题:没将图片储存到用户选定的相册里而将它们都放入了默认相册。出现该问题是因为Discuz是在提交日志文章时将图片放入选定的相册里的,而不是在上传图片时做的。我原来的修改为了给上传图片一个单独的表单,把提交日志文章的表单的范围缩小了,这样漏掉了些缩小前表单的内容如选择的相册,使得提交日志文章后没法将图片放到该相册里。一种改正的办法是将那些表单内容放进缩小后的表单里,但不想这么做了因为要将这些内容从editor_image_menu.htm同时搬到spacecp_blog.htm和spacecp_article.htm。第二种改正的办法是不给上传文件单独的表单,而让它也用提交日志文章的表单。这样的话一个表单里有两个提交按钮,在用户点击提交按钮后,依点击的是哪个按钮在那时刻决定提交给哪个resource来处理,处理完毕后就恢复表单的性质。这就是现在我用的方法。

代码下载: http://www.bian-wang.com/discuz/data/userupload/10005/no_flash_upload.zip (06/14/2016更新)
更新记录:
06/14/2016: 添加繁体UTF-8版文件

发表评论 评论 (76 个评论)

回复 天香公主 2017-10-26 12:21 AM
東里山人: 楼主辛苦了!

DZ有些太坑了~~~

希望楼主早日调试成功,将代码放出来
很粗糙的尝试了下 http://www.bian-wang.com/discuz/home.php?mod=space&uid=10005&do=blog&id=1775
你先试试,如果有问题,我再修改吧
回复 東里山人 2017-10-24 08:17 AM
天香公主: 应该可以做到,我刚在试试js的改动。但估计会有些小的局限。我现在看到的局限是
1)一次选了多个文件后,我可以把它们的名字一一列出,但这些个文件得共享一个删 ...
楼主辛苦了!

DZ有些太坑了~~~

希望楼主早日调试成功,将代码放出来
回复 天香公主 2017-10-23 10:10 PM
東里山人:    楼主有解决办法吗?我一直在找这个,选择时只能单选,影响用户体验,我又不会编程,一直没弄好,楼主能帮忙解决下吗?谢谢。 ...
应该可以做到,我刚在试试js的改动。但估计会有些小的局限。我现在看到的局限是
1)一次选了多个文件后,我可以把它们的名字一一列出,但这些个文件得共享一个删除按钮,点击那个按钮的话,这些个文件就都从上传列表里删除了
2)如果同一次选择多个文件中有一个文件不合要求(比如在选图片时你选了其它文件),我可以给出出错信息,但这次选择中的其它文件也得重新选了
回复 東里山人 2017-10-23 09:54 PM
天香公主: 嗯,我试了试,你说的对。
   楼主有解决办法吗?我一直在找这个,选择时只能单选,影响用户体验,我又不会编程,一直没弄好,楼主能帮忙解决下吗?谢谢。
回复 天香公主 2017-10-23 08:47 PM
東里山人: 我试了,DZ默认的普通上传是没有多图选择功能的,就是加上multiple,也只是可以选多文件,但传递给文件列表时只会剩下一个,最后只能一个一个地选,让要上传的文 ...
嗯,我试了试,你说的对。
回复 東里山人 2017-10-23 09:03 AM
天香公主: 你好,不知你具体指哪个网页上的上传功能。如果是指我文中第二幅图示的帖子图片“普通上传”功能,我记得是可以选择多幅图片的吧? ...
我试了,DZ默认的普通上传是没有多图选择功能的,就是加上multiple,也只是可以选多文件,但传递给文件列表时只会剩下一个,最后只能一个一个地选,让要上传的文件都显示在列表中之后,再点上传,才可以的。也就是说,选择和上传的环节,是可以多文件的,但中间存放文件列表的环节不接受选择的多文件,只保留一个。
回复 天香公主 2017-10-22 03:30 PM
東里山人: 楼主你好。DZ自带的JS上传功能,不支持多文件(多图)上传,请问楼主能帮忙研究下吗?谢谢。
你好,不知你具体指哪个网页上的上传功能。如果是指我文中第二幅图示的帖子图片“普通上传”功能,我记得是可以选择多幅图片的吧?
回复 東里山人 2017-10-22 02:44 PM
楼主你好。DZ自带的JS上传功能,不支持多文件(多图)上传,请问楼主能帮忙研究下吗?谢谢。
回复 天香公主粉丝 2017-5-4 03:10 AM
天香公主: 如果你用的是Firefox,你是象 https://support.mozilla.org/en-US/kb/how-clear-firefox-cache 那样清空缓存的吗?

要不你把你的网址告诉我,我试试看? ...
哈哈哈,谢谢你,我用的是谷歌浏览器,刚换成IE就显示了,原来是浏览器缓存的问题!谢谢你,我的偶像!
回复 天香公主 2017-5-3 11:39 PM
天香公主粉丝: 这个我都删了,改成别的了,更新缓存无数次了,可还是显示原来的呢
如果你用的是Firefox,你是象 https://support.mozilla.org/en-US/kb/how-clear-firefox-cache 那样清空缓存的吗?

要不你把你的网址告诉我,我试试看?
回复 天香公主粉丝 2017-5-3 10:45 PM
天香公主:              是张图片 static/image/common/uploadbutton.png
这个我都删了,改成别的了,更新缓存无数次了,可还是显示原来的呢
回复 天香公主 2017-5-2 09:48 PM
天香公主粉丝: 请问公主!
《选择文件上传》这个按钮的图片或者文字在哪里可以修改呢?我研究了一个多月毫无进展,特来赐教!!! ...
        是张图片 static/image/common/uploadbutton.png
回复 天香公主粉丝 2017-5-2 09:21 PM
天香公主:    谢谢。最近在看看论坛。感觉论坛里有些日志里没有的好的功能,如网站可以在设置里自定义BB代码,又如用户可以给添加的视频定显示尺寸。 ...
请问公主!
《选择文件上传》这个按钮的图片或者文字在哪里可以修改呢?我研究了一个多月毫无进展,特来赐教!!!
回复 carry0987 2016-7-25 10:55 AM
天香公主: 你是说把那个图片加入日志后看不到发布按钮了?你用了我 "iPad上编辑长博文的问题"http://www.bian-wang.com/discuz/home.php?mod=space&uid=10005&do=blog&id ...
喔喔,我沒看到....應該就是這個問題沒錯了
回复 天香公主 2016-7-25 09:31 AM
你是说把那个图片加入日志后看不到发布按钮了?你用了我 "iPad上编辑长博文的问题"http://www.bian-wang.com/discuz/home.php?mod=space&uid=10005&do=blog&id=798 的修改吗?
回复 carry0987 2016-7-25 12:21 AM
天香公主: 但是你的图上是有发布按钮的啊?
我试了在iPad上没问题。
狀況:
回复 carry0987 2016-7-25 12:14 AM
天香公主: 但是你的图上是有发布按钮的啊?
我试了在iPad上没问题。
iPhone 5 上沒辦法....
回复 天香公主 2016-7-25 12:13 AM
carry0987: 關閉後看不見我才告訴你的......我試過很多方法..
但是你的图上是有发布按钮的啊?
我试了在iPad上没问题。
回复 carry0987 2016-7-25 12:07 AM
天香公主: 在点击添加图片到日志里后,点击选择图片框的右上角的关闭按钮将该框关闭后,就可以看到发布日志的按钮了吧? ...
關閉後看不見我才告訴你的......我試過很多方法..
回复 天香公主 2016-7-24 10:50 PM
carry0987: 小問題:在iphone上選擇相冊圖片時,如果圖片太長,會造成遮住發表日誌的按鈕 ...
在点击添加图片到日志里后,点击选择图片框的右上角的关闭按钮将该框关闭后,就可以看到发布日志的按钮了吧?
1234下一页

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 立即注册

小黑屋|Archiver|彼岸网  

Powered by Discuz! X3.1 © 2001-2014 Comsenz Inc.
GMT-4, 2017-11-25 03:51 AM , Processed in 0.064282 second(s), 19 queries.

返回顶部