先来看一下最终效果:
点击左上角的按钮,可以从后台获取stl文件,并且显示。
3DSTL_2.png
其中,按钮的代码为:<button onclick="read_file('test/testStl.do')">點擊獲取3D文件(stl,obj,vf)</button>
,其调用的方法,笔者已经封装为read_file('test/testStl.do')
,可以看出是调用了后端的controller得到相应的文件。
以下是实现过程:
-
收集实现代码
首先,需要一个显示stl的前端实现。因为是前端代码,并且是显示比较主流的3D文件,所以肯定是已经有相应的实现,所以我们要做的就是找到相应的实现,然后在上面做相应的修改即可。笔者参考的是以下这个stl免费在线查看工具:free online STL viewer.因为这个工具已经标注了完全在本地运行,所以我们肯定能够通过这个网站的前端源码实现我们的需求。
-
下载源码
新建文件夹
stlShow
,在上面的网页下ctrl+s
保存代码到此文件夹。此时我们可以看到在其js文件夹下所有的js文件都是.下载
结尾了,我们首先删除.下载
后缀,然后打开Free online STL viewer.html
,搜索.下载
,并删除所有.下载
后缀。
-
后端编写
stl
文件controller首先准备一个
test.stl
文件放在webapp
下。@Controller public class TestDemonController { @RequestMapping(value = "/testStl.do") @ApiOperation(value = "以二进制流的形式传送STL") public void getTestSTL(HttpServletRequest request, HttpServletResponse response){ FileInputStream fis = null; String stlPath = request.getSession().getServletContext().getRealPath("")+"test.stl"; //这里的类型,是笔者在调试前端js代码的时候找到的,默认的类型里面没有这一类型,但是此类型是必须要写的 response.setContentType("application/vnd.ms-pki.stl"); out(request,response,fis,stlPath); } private void out(HttpServletRequest request, HttpServletResponse response,FileInputStream fis,String path){ try { OutputStream outputStream = response.getOutputStream(); File file = new File(path); fis = new FileInputStream(file); byte[] b = new byte[fis.available()]; fis.read(b); outputStream.write(b); outputStream.flush(); } catch (IOException e) { e.printStackTrace(); }finally { if(fis!=null){ try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
在浏览器中输入
your-url/testStl.do
,能够下载一个testStl.do
文件,将其改名为testStl.stl
,上传到最初的那个网站,可以看到效果,说明接口已经正常运行。 -
拷贝前端代码至你的项目中
将前端代码拷贝到你的web项目中,并根据你拷贝的情况修改js引用路径。
-
修改前端代码
read_internal.js
替换
read_internal.js
文件中function read_file(f)
方法为(具体解释请看注释):function read_file(stl_url) { waiting=true; var pbar=$id('file_pbar'); var reader = new FileReader(); reader.onerror = function(e) { var error_str=""; switch(e.target.error.code) { case e.target.error.NOT_FOUND_ERR: error_str="File not found"; break; case e.target.error.NOT_READABLE_ERR: error_str="Can't read file - too large?"; break; case e.target.error.ABORT_ERR: error_str="Read operation aborted"; break; case e.target.error.SECURITY_ERR: error_str="File is locked"; break; case e.target.error.ENCODING_ERR: error_str="File too large"; break; default: error_str="Error reading file"; } alert(error_str); switch_view('drag'); return after_error(); } reader.onload = function(e) { switch_view('proc'); setTimeout(function(){after_file_load('3D圖片展示', e.target.result)}, 500); }; reader.onprogress = function(e) { if (cancel_download) { reader.abort(); return after_error(); } else pbar.value=e.loaded / e.total*100; }; pbar.value=0; //使用一个回掉函数获取stl文件的二进制流为blob类型 //使用Jquery的$.Ajax方法虽然能得到二进制数据,但是没有类型,甚至不是Array的类型,所以这里采用了这个方式 switch_view('pbar'); var stl; var xhr = new XMLHttpRequest(); xhr.open('GET', stl_url, true); xhr.responseType = 'blob'; xhr.onload = function(e) { if (this.status == 200) { // get binary data as a response stl = this.response; reader.readAsArrayBuffer(stl);//调用原来的方法把stl文件传入 } }; xhr.send(); }
-
修改
parser.js
文件parser.js
文件是用来解析文件类型的,我们通过后端传入的文件因为没有文件名,所以这边会将我们传入的文件判断为不支持的类型,所以,这边我们用一个比较笨的方法,解决这个问题,之后如果需要解析obj
orvf
文件,可以自行修改。这里,我们修改function parse_3d_file(filename, s)
函数为:function parse_3d_file(filename, s) { //determine type of file //console.log(filename.split('.').pop().toLowerCase()); switch (filename.split('.').pop().toLowerCase()) { case "stl": return parse_stl_bin(s); break; case "obj": return parse_obj(s); break; case "vf": return parse_vf(arrayBufferToString(s)); break; default: return parse_stl_bin(s);//直接调用stl解析 break; } }
-
添加测试按钮
在
Free online STL viewer.html
中添加按钮<button onclick="read_file('test/testStl.do')">點擊獲取3D文件(stl,obj,vf)</button>
。测试效果如文章开头所示。 -
删除掉
Free online STL viewer.html
中你不需要的代码
自此,stl 3D文件的自定义demon已经完成,作为一个后端开发人员,看到这6K多行的js代码,简直是头痛,特别是js基础不是很好,确实是个不小的挑战。个人感觉js代码相对于java这样的代码来说,大多时候更缺少比较严密的工程组织,不过据说现在的前端已经工程化了,希望以后看到更新的js代码时不会那么吃力:)。
网友评论