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

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

日志

如何在普通上传中支持一次多选

热度 4已有 229 次阅读2017-10-25 10:47 PM |个人分类:Discuz

本文探讨下如何在论坛里的普通上传(即在不支持Flash或没激活Flash的情形)中支持一次选择多个文件。 Discuz的这个功能允许多次选择多个文件后上传,但每次选择只能选择一个文件。在PHP里支持一次选择多个文件的要点参见网页 http://php.net/manual/zh/features.file-upload.multiple.php 上的解释。

首先是图示:

1。点击工具栏里的图片图标后,出现选择图片对话框:


2。点击选择按钮后,在选择文件对话框里可以选择多个文件:


3。显示所有选中的图片名:


4。点击上传后:




下面介绍下要修改的代码:

1) 需要改变file元素的属性使之能同时选择多个文件
在 template/default/forum/editor_menu_forum.htm里,有两个file元素,一个用于上传图片 <input name="Filedata" size="45" class="filedata" type="file"> 另一个用于上传附件 <input type="file" name="Filedata" size="45" class="filedata" /> 都改为 <input name="Filedata[]" size="45" class="filedata" multiple="multiple" type="file"> 其中添加multiple属性是为了在选择文件框里能选择多个文件,name的修改是PHP的要求使得在服务器端能得到上传的多个文件。

2) 当选择完成后要在网页上要显示所有选择的文件 在 static/js/forum_post.js 的函数addAttach中,需要做两处修改。首先由于我们上面改了file元素的name,所以在函数 addAttach 里需要将下面这句 if(tags[i].name == 'Filedata') { 改成 if(tags[i].name == 'Filedata[]') { 其次函数insertAttach是用于在网页上显示选择后的文件的,原来的代码从file元素的value值中得到选择的文件名,这种方式得不到多个文件名。在多选的情况下,它还是只含有一个文件名。而file元素的files值是一个数组,其中每个元素对应了选择的一个文件。我们要将这个函数里的下面部分 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; } 改成 var files = $(prefix + 'attachnew_' + id).files; if (!files) return; var filename = ''; var localfile = ''; for (var i = 0; i < files.length; i++) { var path = files[i].name; var extpos = path.lastIndexOf('.'); var ext = extpos == -1 ? '' : path.substr(extpos + 1, path.length).toLowerCase(); var re = new RegExp("(^|\\s|,)" + ext + "($|\\s|,)", "ig"); 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; } if (i > 0) filename += '; '; filename += path; if (i > 0) localfile += '; '; localfile += path.substr(path.replace(/\\/g, '/').lastIndexOf('/') + 1); }
3) 需要修改当点击上传后接受上传的代码
由于上面对客户端添加了上传多个文件的支持,在服务器端收到的诸如$_FILES['Filedata']['name'],$_FILES['Filedata']['type']等值不再是字符串,而成了数组。数组的长度由上传文件的个数决定,其中每个元素记载了一个文件的相应属性。所以我们需要对PHP代码做些调整,来支持保存多个文件。需要修改两个PHP文件。
3a) 在source/module/misc/misc_swupload.php中将下面这句 $upload = new forum_upload(); 改为 if (is_array($_FILES['Filedata']['name'])) { $count = count($_FILES['Filedata']['name']); $file_keys = array_keys($_FILES['Filedata']); for($i=0; $i<$count; $i++) { $fd = array(); foreach ($file_keys as $key) { $fd[$key] = $_FILES['Filedata'][$key][$i]; } $upload = new forum_upload(0, $fd); } } else { $upload = new forum_upload(); } exit; 3b) 在文件 source/class/forum/forum_upload.php 里,将下面这句 function forum_upload($getaid = 0) { 改为 function forum_upload($getaid = 0, $filedata) { 然后将下面这段 $upload = new discuz_upload(); $upload->init($_FILES['Filedata'], 'forum'); 改为 if (empty($filedata)) $filedata = $_FILES['Filedata']; $upload = new discuz_upload(); $upload->init($filedata, 'forum'); 最后将函数uploadmsg里的最后一句 exit; 改成 if ($statusid) exit;

发表评论 评论 (24 个评论)

回复 東里山人 2017-11-18 01:46 AM
天香公主: 看了下你说的那个js文件,的确和电脑版做法完全不同,它用的是html5里的File API还有画布canvas。在画布上可以将图片变形,所以它能起到压缩图片的效果。 ...
可以将电脑版的JS上传(非FLASH)改成由这个文件来完成吗?
回复 天香公主 2017-11-18 12:53 AM
東里山人: 我用的是UC浏览器,内核就是Chrome的,用了检查(开发模式)模拟手机,使用DZ默认的移动端模板,并将/static/js/mobile/buildfileupload.js中的“maxheight”和 ...
看了下你说的那个js文件,的确和电脑版做法完全不同,它用的是html5里的File API还有画布canvas。在画布上可以将图片变形,所以它能起到压缩图片的效果。
回复 東里山人 2017-11-18 12:37 AM
天香公主: 有趣,能否再试试从电脑上进入手机版网站后是否也会先压缩再上传?从电脑上进入手机版网站的方法可以参照 https://deviceatlas.com/blog/how-to-change-user-age ...
我用的是UC浏览器,内核就是Chrome的,用了检查(开发模式)模拟手机,使用DZ默认的移动端模板,并将/static/js/mobile/buildfileupload.js中的“maxheight”和“maxwidth”赋值都改为“200”,其他后台未做任何修改,用移动端模板上传了一张“338X450”的图片,得到一张“151X200”的图片;再回到PC端模板上传同样图片,得到一张“338X450”的图片。不止如此,buildfileupload.js似乎还会判断“exif”中的“Orientation”然后对图片进行处理。

不过DZ的手机模板在插入图片上有问题,我用默认模板,点击图片无反应,用第三方模板点击图片,只会插入到帖子内容的最后面,无法根据光标定位插入。

现在我用的移动端编辑器,是有人移植PC端的代码,所以一直以为移动端没有先压缩的功能。如果能综合一下两个编辑器的上传图片功能,就比较理想了。不过我的水平,看都看不懂,别说改了
回复 天香公主 2017-11-17 11:33 PM
東里山人: 之前的说法错语,DZ在PC端的上传是没有先压缩的,但移动端的上传是有压缩的,我的移动端编辑器使用的上传代码是PC端的,所以才没有压缩功能   ...
有趣,能否再试试从电脑上进入手机版网站后是否也会先压缩再上传?从电脑上进入手机版网站的方法可以参照 https://deviceatlas.com/blog/how-to-change-user-agent-in-desktop-browser
回复 東里山人 2017-11-17 09:40 AM
天香公主: 哦,是因为文件过大产生的问题,那就可以理解了。这也说明这种修改的另一个局限,那就是同一次选择的多个文件是同时上传的,无法分开来一一上传。

现在人拍的照 ...
之前的说法错语,DZ在PC端的上传是没有先压缩的,但移动端的上传是有压缩的,我的移动端编辑器使用的上传代码是PC端的,所以才没有压缩功能
回复 東里山人 2017-11-14 08:31 AM
天香公主: 哦,是因为文件过大产生的问题,那就可以理解了。这也说明这种修改的另一个局限,那就是同一次选择的多个文件是同时上传的,无法分开来一一上传。

现在人拍的照 ...
DZ确实是上传后在服务器端压缩处理图片的,我找了一些能在上传前由客户端先压缩再上传的JS代码,但考虑一下自己的水平估计很难合并进去,而且有可能把手机内存撑爆了……所以只能等官方能不能解决了。
回复 天香公主 2017-11-2 10:14 PM
loveyou520tw: 該怎麼說呢,會覺得受益非淺是因為修改同時也了解到如何debug一些問題,所以覺得非常受益非淺。
這邊確實Discuz有一個很奇怪的問題,若不用flash上傳,發布帖子 ...
哦,是因为文件过大产生的问题,那就可以理解了。这也说明这种修改的另一个局限,那就是同一次选择的多个文件是同时上传的,无法分开来一一上传。

现在人拍的照片像素越来越高,经常看到有网友抱怨无法上传照片。其实html5提供了在浏览器里在上传前先缩小尺寸的办法。从网上的讨论看好像最近版本的swfupload也提供了类似功能,但好像Discuz里只在服务器端在上传后才缩小尺寸。我觉得在客户端缩小尺寸应该是个必需的功能,但自己自起炉灶的添加这类功能就有点不值得了,不如弃swfupload,而改用一个同时基于flash和html5的上传工具,那这样的功能就都有了。
回复 loveyou520tw 2017-11-2 09:30 PM
天香公主: 不客气啦。其实我对这个修改不太满意,只是有网友问了就试图回答一下。不满意的主要原因是一次选择的多个文件没法各个分别删除。完全基于html5的文件上传工具应 ...
該怎麼說呢,會覺得受益非淺是因為修改同時也了解到如何debug一些問題,所以覺得非常受益非淺。
這邊確實Discuz有一個很奇怪的問題,若不用flash上傳,發布帖子後再回來編輯是無法刪除附件的,還必須再上傳一張附件才會出現先前上傳的附件才能夠刪除,這真的是一個嚴重的操作不良。

關於沒法上傳部分,我這邊測試debug出來是服務器上限大小問題,我服務器上設置最大10M,所以多檔上傳的時候若檔案超過10M就會出現無法上傳的問題,這是剛剛測試出來的結果,所以才會出現內部錯誤。
建議天香老師上面附註一下,若同時多檔選擇超過服務器上傳限制,是會出現內部服務器錯誤的。
回复 天香公主 2017-11-2 09:15 PM
loveyou520tw: 這邊先感謝天香老師的分享修改!真的非常實用受益非淺,這邊也剛好有這個需求,畢竟Flash已經宣布準備要停用了,這個修改是必須的。

我這邊回報一下給天香老師問 ...
不客气啦。其实我对这个修改不太满意,只是有网友问了就试图回答一下。不满意的主要原因是一次选择的多个文件没法各个分别删除。完全基于html5的文件上传工具应该没有这个局限,但是要沿用Discuz的现有办法(用隐藏的iframe来提交上传文件)的话这个局限就没法克服了。

你说没法上传,这有点奇怪。请问没改以前可以上传吗?如果那时是可以上传的,请再检查下PHP代码的修改(文中第三部分)
回复 loveyou520tw 2017-11-2 08:56 PM
這邊先感謝天香老師的分享修改!真的非常實用受益非淺,這邊也剛好有這個需求,畢竟Flash已經宣布準備要停用了,這個修改是必須的。

我這邊回報一下給天香老師我自己遇到的問題,參照修改後可多選檔案了,但會無法上傳唷。
會顯示一則內部錯誤。
---更新---
後來測試之後發現 ...
若一次上傳一定張數會出現錯誤,我這邊研判應該是我自己伺服器的設定錯誤。
---更新2----
測試完畢,確實是我這邊的服務器設定上一些問題
因為我這邊設定上傳檔案大小只有2M,所以如果多選後超過2M就會出現內部服務器錯誤,哈哈
回复 天香公主 2017-11-2 11:42 AM
東里山人: 不会用GIT 我是自家网站够用就行,如果发现有问题或需要某项功能,就只能四处找代码
我也几乎不用Git。曾经把Discuz代码放在Visual Studio Online里使用感觉不错。我过去介绍过 http://www.bian-wang.com/discuz/home.php?mod=space&uid=10005&do=blog&id=1520
回复 東里山人 2017-11-2 11:04 AM
天香公主: 嗯,能不改还是不改的好,比如本文里说的改动在我看来不值一改。真要改的话,最好把网站代码放在一个版本控制系统里,如Git。 ...
不会用GIT 我是自家网站够用就行,如果发现有问题或需要某项功能,就只能四处找代码
回复 牛肉炖土豆 2017-10-30 11:03 AM
看了两位的讨论,又学到了知识!我越来越觉得自己想弄清楚问题的太多了,感觉是无底洞,呜呜,希望早日能学到天香的一半境界!
回复 天香公主 2017-10-29 11:32 PM
ladyff: 如果想要同时显示普通上传和flash上传呢
在文件editor_menu_forum.html里,把下面这句
<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>
改成
<li id="{$editorid}_btn_local"><a href="javascript:;" hidefocus="true" onclick="switchImagebutton('local');">{lang normal_upload}</a></li>
即可
回复 ladyff 2017-10-29 11:19 PM
天香公主: 你记得没错,普通上传只在不支持Flash和没激活Flash的浏览器里才出现。

关于你的问题,应该有多种改法。比如在upload.js里将
  loading : swfobject.hasFlashPl ...
如果想要同时显示普通上传和flash上传呢
回复 天香公主 2017-10-29 09:17 PM
ladyff: 我怎么记得discuz在检测到浏览器支持flash的时候,会自动使用flash,同时隐藏这个普通的上传框?

能不能改下代码强制不使用swfupload ...
你记得没错,普通上传只在不支持Flash和没激活Flash的浏览器里才出现。

关于你的问题,应该有多种改法。比如在upload.js里将
  loading : swfobject.hasFlashPlayerVersion("9.0.28"),
改为
  loading : false,
即可。
回复 ladyff 2017-10-29 07:39 PM
我怎么记得discuz在检测到浏览器支持flash的时候,会自动使用flash,同时隐藏这个普通的上传框?

能不能改下代码强制不使用swfupload
回复 天香公主 2017-10-29 10:52 AM
東里山人: Discuz在使用过程中,会发现很多的大坑,光是修改源代码,都会改到不想升级,因为改动的地方太多了,有时都会忘了改过啥。

有些坑存在很多年,提出的人非常多, ...
嗯,能不改还是不改的好,比如本文里说的改动在我看来不值一改。真要改的话,最好把网站代码放在一个版本控制系统里,如Git。
回复 天香公主 2017-10-29 10:46 AM
東里山人: 我把楼主的:if (i > 0) filename += '; ';
改成:if (i > 0) filename += ';\<br\> ';

这样文件列表会换行,看起来好一点,原来的所有文件名只排在同一行中, ...
嗯,分成多行不错。我没这么做是因为这样的话只有第一个图左侧有图标,右侧有删除按钮,怕看上去效果不好。
回复 東里山人 2017-10-29 12:13 AM
我把楼主的:if (i > 0) filename += '; ';
改成:if (i > 0) filename += ';\<br\> ';

这样文件列表会换行,看起来好一点,原来的所有文件名只排在同一行中,不熟悉的会误认为只有一个文件。
12下一页

facelist doodle 涂鸦板

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

小黑屋|Archiver|彼岸网  

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

返回顶部