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

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

日志

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

热度 5已有 766 次阅读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 = null) { 然后将下面这段 $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;

发表评论 评论 (35 个评论)

回复 天香公主 2018-1-1 01:18 AM
ladyff: 修改后确实可以了。我是php 7.1
好,我在文中把这个默认值加上去了
回复 ladyff 2017-12-31 11:50 PM
天香公主: 对,我没用https。但应该与此无关,错误信息说是在调用函数forum_upload时传递了太少的变量值,但在我的环境下这是允许的,估计与php的版本或某个设置有关。

建 ...
修改后确实可以了。我是php 7.1
回复 天香公主 2017-12-30 11:09 PM
ladyff: 刚建了个测试站,https://www.gladknow.com/
你可以试一下。
我怀疑是不是Https的问题,你测试的时候是不是没有Https?
对,我没用https。但应该与此无关,错误信息说是在调用函数forum_upload时传递了太少的变量值,但在我的环境下这是允许的,估计与php的版本或某个设置有关。

建议把文件source/class/forum/forum_upload.php里的下面这句
    function forum_upload($getaid = 0, $filedata) {
改为
    function forum_upload($getaid = 0, $filedata = null) {
试试
回复 ladyff 2017-12-30 06:38 AM
天香公主: 我刚才把前面说的那句让普通上传和flash上传同时显示的修改加上去了,测试下来flash上传也还是能用的。我的测试步骤是在论坛首页点击默认版块,点击发贴按钮,在 ...
刚建了个测试站,https://www.gladknow.com/
你可以试一下。
我怀疑是不是Https的问题,你测试的时候是不是没有Https?
回复 天香公主 2017-12-29 10:49 PM
ladyff: 这个我还真没试。晚上我新建个网站试试
比较理想的做法是2个都启用,用户可以自己选啊。然后将来flash不行了直接干掉flash上传。 ...
我刚才把前面说的那句让普通上传和flash上传同时显示的修改加上去了,测试下来flash上传也还是能用的。我的测试步骤是在论坛首页点击默认版块,点击发贴按钮,在发表贴子页选择图片发贴。如果你的步骤和我不同,说说你的步骤我再试试。或者告诉我你的网址,我去你那试试。
回复 ladyff 2017-12-29 09:05 PM
天香公主: 哦,那如果把“同时启用了普通上传和flash上传”部分去掉的话,flash上传没问题吧?
这个我还真没试。晚上我新建个网站试试
比较理想的做法是2个都启用,用户可以自己选啊。然后将来flash不行了直接干掉flash上传。
回复 天香公主 2017-12-28 10:34 PM
ladyff: 比较了一下,咱俩修改是一致的。
唯一的区别是我按照你之前的提示同时启用了普通上传和flash上传(就是 有flash安装了也显示普通上传) ...
哦,那如果把“同时启用了普通上传和flash上传”部分去掉的话,flash上传没问题吧?
回复 ladyff 2017-12-28 10:24 PM
天香公主: 应该是没问题的,我写这篇博文时是在简体中文UTF8版的X3.2里试的,刚才又新装了简体中文UTF8版的X3.4后加上了文中所述的修改,在64bit的Win7里在IE11/FF57/GC63 ...
比较了一下,咱俩修改是一致的。
唯一的区别是我按照你之前的提示同时启用了普通上传和flash上传(就是 有flash安装了也显示普通上传)
回复 天香公主 2017-12-27 11:06 PM
ladyff: 发现一个问题
用这个方法修改后,普通上传工作正常,而flash上传就出现错误了。
上传一张取消一张。。就是长传到100%就会显示取消上传 ...
应该是没问题的,我写这篇博文时是在简体中文UTF8版的X3.2里试的,刚才又新装了简体中文UTF8版的X3.4后加上了文中所述的修改,在64bit的Win7里在IE11/FF57/GC63三个浏览器里激活了Flash,测试了论坛里的上传图片都有没问题。我把改动的文件放上来了,你可以对比一下
http://www.bian-wang.com/discuz/data/userupload/10005/normal_upload_multi_select_X3.4_SC_UTF8.zip
或者新装个简体中文UTF8版的X3.4把这些文件拷贝过去再试试?
回复 ladyff 2017-12-27 12:44 AM
发现一个问题
用这个方法修改后,普通上传工作正常,而flash上传就出现错误了。
上传一张取消一张。。就是长传到100%就会显示取消上传
回复 东风 2017-12-18 12:18 PM
  
回复 東里山人 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代码的修改(文中第三部分)
12下一页

facelist doodle 涂鸦板

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

小黑屋|Archiver|彼岸网  

Powered by Discuz! X3.1 © 2001-2014 Comsenz Inc.
GMT-4, 2018-2-24 11:35 AM , Processed in 0.056346 second(s), 8 queries. ,ApcOn

返回顶部