用 WebBroker 开发 Web 服务器,前端用 CKEditor 的话,如何上传图片,自动贴图?以前在 FCKEditor 的年代(asp.net 1.0 的时代),我是自己上传图片文件然后自己在服务器端把图片写入 FCKEditor 里面的。
现在查网上的资料,大多是针对 JAVA 写的服务器,并且都是抄同一篇文章,还没抄清楚。也有针对 C# 的。没有针对 Delphi WebBroker 的。
图片文件上传,和文件上传是一样的,需要服务器端有程序来接收处理。单纯靠 WEB Server 比如 IIS 是不行的。我这里采用 Delphi 的 WebBroker 的程序在服务器端处理图片上传。这里面的概念其实很简单:
1. 前端 CKEditor 的贴图对话框界面,要有上传图片的界面,并且,要能够指定上传到哪里,也就是上传到我的 WebBrloker 程序的哪个 Path 底下。
2. 服务器端程序收到上传的文件后,保存文件等操作完以后,如何通知 CKEditor 保存的上传图片的 URL 地址,方便 CKEditor 将图自动贴进去并显示出来。
3. CKEditor 上传完成并接收到来自服务器的返回值,根据返回值,自动将接收到的图片 URL 贴进去。只要 URL 正确,图片就显示出来了。
如果对一次 WEB 访问的流程清楚的话,就会知道这是一个浏览器对 WEB 服务器的 Post 操作,Post 数据过去服务器并接收到返回值(返回值其实也是一个字符串)。
概念讲完,以下是实际做法和代码:
CKEditor 的工具栏上,有一个图片按钮,贴图用。点这个按钮,会弹出一个窗口,窗口有两个页标签:图像;高级。这里没有上传图片的页标签。
其实这个页标签是有的,只是它的默认设置没有。要显示这个页标签,打开文件:ckeditor\plugins\image\dialogs\Image.js
在这个 js 文件里面搜索:id:"Upload",hidden:!0 这个字符串,把前面的 ! 去掉。再刷新页面,就能看到上传图片的页标签了。
然后,继续设置上传图片的 URL 地址。打开:ckeditor/config.js 这个文件,添加以下代码:
var pathName = window.document.location.pathname;
var projectName = pathName.substring(0, pathName.substr(1).indexOf('/') + 1);
config.filebrowserImageUploadUrl = projectName+'/MyUpload';
备注:最后一行的 MyUpload 必须是你的服务器端程序处理浏览器上传文件的 WebBroker 的 Action 的 Path 名字。
--------------------------
服务器端返回上传后的图片路径给 CKEditor :
上述服务器端处理来自 CKEditor Post 的上传图片文件以后,如果回送:
Response.Content := '<font color="red>上传成功</font>' 则在该图片上传界面里面会显示一行红色的字。这个用于上传的文件不是图片或者其它什么警官的时候。
如果回送一段 JavaScript,则可以让CKEditor的图片上传窗口接收到上传的图片的 http 地址,用户点“确定”后,图片会显示在窗口里面。再次点确定,图片就直接贴入 CKEditor 里面了。这段 JS 如下:
CKEditorFuncNum := '1';
JS := '<html><body><script type="text/javascript">window.parent.CKEDITOR.tools.callFunction(' +
CKEditorFuncNum + ',' + '"http://localhost/dcgi/' + AFileName + '", "Upload Successed!");</script></body></html>';
这段 JS 测试通过。这段 JS 代码的 callFunction 函数里面,第一个参数是数字 1,第二个参数是上传的图片在服务器里面的 URL 地址,返回给 CKEditor 自动贴图用,第三个参数是显示消息,CKEditor 会弹窗显示。
也就是说,上传完成后,直接返回一段 JS 就可以让 CKEditor 执行贴图的动作。
奇怪的是,上传完成后,也就是 CKEditor Post 以后,CKEditor 还会再次对上传地址发起一个 Get 操作,其 Request.QueryFields 的内容如下:
CKEditor=MyMemo
CKEditorFuncNum=1
langCode=zh-cn
就是这个 Get 操作误导了我,使我浪费很多调试时间。因为,它这个访问同样进入了 WebBroker 的处理上传的 Path 里面,却没有上传文件,而是一个 Get 操作。并且,这个 Get 操作的参数仅仅是 CKEditorFuncNum=1, 服务器端无法根据这个操作,来判断上一次访问(Post) 传的是什么文件。而且目前看来,这个 Get 操作也没有任何意义。不知道它是想干什么?难道是想获得上传图片的文件列表,用于在图片上传框里做服务器端文件列表的显示?
----------------
又:
CKEditor 上传文件到哪个路径的配置,可以不用写在 CKEditor 的 config.js 里面,而是直接写在页面 html 代码里面:
<textarea name="MyMemo"><#DocContent></textarea>
<script type="text/javascript"> CKEDITOR.replace("MyMemo", {
filebrowserBrowseUrl : 'FileBrowser',
filebrowserImageBrowseUrl : 'FileBrowser?type=Images',
filebrowserUploadUrl : 'upload',
filebrowserImageUploadUrl : 'upload?type=Images'});
</script>
经过在服务器端用 WebBroker 写代码来验证:
1. filebrowserImageUploadUrl 这个参数,是在 CKEditor 的贴图对话框里面的上传图片,使用的服务器端路径;虽然它是一个 Post 操作,但也可以通过 Request.QueryFields 读到这个路径后面的 type=Images 的值。
2. filebrowserUploadUrl 这个参数,是 CKEditor 的链接图标点出来的对话框里面的文件上传操作的服务器端路径。在服务器端来看,可以用同一个路径也就是同一段代码来处理文件上传和图片上传,如果服务器端代码要区别是来自文件上传还是图片上传,则根据问好后面的 QueryFields 来区别。
3. filebrowserBrowseUrl 这个参数是链接对话框里面的“浏览服务器”按钮,弹出来的网页,所访问的服务器端路径。服务器端的对应代码,可以用来将服务器端的文件做成一个列表显示在网页里面,让用户选择。
4. filebrowserImageBrowseUrl 这个参数,是图片对话框里面的 “浏览服务器” 按钮弹出来的网页所访问的服务器端路径。处理同上。