Autodesk Forge API服务的数据中心是基于AWS的海外服务搭建的,因而,由于众所周知的原因,国内部分地区(依ISP而异)访问Forge云端口的速度会受到一定程度的影响。特别是Forge Viewer浏览大型模型,以及对反馈时间比较铭感且涉及关键业务的工作流等诸多场景,对于服务端的存取效率有者较高要求。所以,如何处理好云端数据的访问与协同工作流,包括离线加载、云端缓存等方案的最佳实践,是大家一直关注的问题。今天,我们就总结一下几种常见的实现方式,以期实现流程与性能的优化。离线模型加载往期有这两篇文章可供参考:离线模型的下载和部署和Viewer模型加载本地离线缓存实战,该文介绍了使用新近浏览器原生的Service-Worker和Cache API缓存模型的方案。但是在Viewer模型加载本地离线缓存实战的实例代码中,针对Viewer库和线上模型资源本身的缓存是通过静态路径实现的://https://github.com/petrbroz/forge-disconnected/blob/master/public/service-worker.jsconst STATIC_URLS = [ ‘https://developer.api.autodesk.com/modelderivative/v2/viewers/6./style.css’, ‘https://developer.api.autodesk.com/modelderivative/v2/viewers/6./viewer3D.js’, ‘https://developer.api.autodesk.com/modelderivative/v2/viewers/6./lmvworker.js’, ‘https://developer.api.autodesk.com/modelderivative/v2/viewers/6./res/locales/en/allstrings.json’, ‘https://developer.api.autodesk.com/modelderivative/v2/viewers/6./res/environments/SharpHighlights_irr.logluv.dds’, ‘https://developer.api.autodesk.com/modelderivative/v2/viewers/6./res/environments/SharpHighlights_mipdrop.logluv.dds’,…该实现存在几点问题:待缓存的静态链接是根据展示用的模型所需配置的,模型更换后静态链接也需要手动更新一次性缓存了所有实例模型所需的资源,超配且不必要,影响加载性能Viewer库版本一旦更新,需手动更新缓存的静态资源链接因此,在我们后续的实战Forge Viewer渐进应用一文中,采用先注册完成缓存任务的Service Worker再加载Viewer库的流程。如此一来,Viewer库依赖与模型资源的加载请求也会自动得到缓存,无需手动干预缓存过程,大幅增进代码的可维护性:navigator.serviceWorker.register(’/service-worker.js’).then((registration) => { let script = document.createElement(‘script’); script.onload = function () { const viewer = new Autodesk.Viewing.Private.GuiViewer3D(myViewerDiv); Autodesk.Viewing.Initializer(options, () => { … //按需以在线或离线模式初始化Viewer并加载模型 viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, () => { const channel = new MessageChannel(); channel.port1.onmessage = (event) => console.log(event); navigator.serviceWorker.controller.postMessage({ operation: ‘EXECUTE_CACHE’ }, [channel.port2]); // 模型加载完成,该模型所需资源已作记录,遂向ServiceWorker发送消息,开始缓存所需资源 }) }); }; script.src = “https://developer.api.autodesk.com/modelderivative/v2/viewers/6.*/viewer3D.min.js”; document.head.appendChild(script) //待Worker注册完毕开始作动后再载入Viewer,实现Viewer库及其依赖的自动缓存})在线模型加载建议参考下文的数据服务的优化,为Viewer的加载提供代理,增进国内访问的速度。在Viewer上实现代理的方法主要通过Autodesk.Viewing.endpoint.setEndpointAndApi来重定向获取模型数据的URL:Autodesk.Viewing.Initializer(options, function(){ Autodesk.Viewing.endpoint.setEndpointAndApi(‘https://yourhostname/your/proxy/service/path’)…随后在你的服务端将Viewer发来的请求代理至Forge API云服务https://developer.api.autodesk.com即可,注意保留Viewer原生请求的路径,这里还可以根据Forge服务上的模型所在的数据中心按需为转发目的地作进一步设置,详见:BIM 360 Docs API在操作欧洲数据中心内容的一些调整。亦可设置Viewer发送的请求头,以AOP的设计模式实现自己的访问控制等逻辑:Autodesk.Viewing.Initializer(options, function(){ Autodesk.Viewing.endpoint.HTTP_REQUEST_HEADERS = {‘X-My-Custom-Header’:‘233’, …}…当然,我们还需在自己的服务端设置预检请求(Pre-flight)的返回中Access-Control-Allow-Headers的请求头,允许之前为Viewer设置的请求头不被浏览器的跨域安全机制拦截。当然,大家熟悉的Viewer原生的getAccessToken等都是依旧有效的。Android如本地的模型,由于Viewer不支持基于File协议的模型加载,需要通过重写WebView并拦截http请求,返回静态资源。webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith(“http://my/path/to/svf”)) { // 返回静态模型资源 return true; } }});Viewer加载模型的URL维持http协议即可iOS同理,iOS的实现思路是: func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Swift.Void) { if navigationAction.navigationType == .linkActivated { if webView.url!.absoluteString == “http://path/to/my/static/svf” { //返回静态模型资源 return } } decisionHandler(.allow)}亦可参考这里的教程:https://github.com/BKRApps/KR…跨平台针对跨平台的框架,不建议使用搭设本地静态服务器的方式克服Viewer不支持File协议的问题,因为很多Android ROM处于安全考量已经屏蔽了该特性。React Native框架: 推荐使用react-native-webview,再通过onShouldStartLoadWithRequest拦截并返回静态模型:onShouldStartLoadWithRequest = (event) => { var url = event.url; if (url && url.length) { if (url.indexOf(‘http://my/path/to/svf’) == 0) { //返回静态模型资源 } } return true; };Ionic框架推荐使用cordova-plugin-ionic-webview,再通过onShouldStartLoadWithRequest拦截并返回静态模型再结合Cordova File Plugin访问静态资源cdvfile://path/to/svf数据服务的优化建议自建云服务访问Forge API或部署代理,以便实现诸多优化事项,如缓存(可以使用http-cache等库),如集中统筹Access Token,避免为每个客户端服务请求逐一作Forge认证,提升效率的同时增强Forge App密钥和Token的安全性,亦便于实现高度自定的工作流。建议搭建位于海外机房的节点作代理,地理位置推荐香港或接入电信CN2线路的北美机房,访问速度会有不小提升,详情可以自行搜索了解。亦可搭建自己的云存储,便于实现高度自定义的工作流与高规格的安全机制,可以通过等Ceph和minio等技术实现。活用Forge Webhook API,实现基于事件回调的异步工作流,节省资源的同时提高可靠性,详情可以参考这些样例。Q&AQ:能否避免将模型上传到Forge数据平台,直接进行转换?A:Forge服务只能转换存储在Forge数据平台的模型,转换功能无法作本地部署,如模型涉密,可以再转换完成后立即从Forge数据平台删除,Forge对用户数据不作任何备案。Q:可否实现Viewer的完全本地化?即将Viewer库和模型渲染资源下载到本地?A:Forge Viewer使用许可禁止将Viewer库下载至本地加载,亦禁止对代码进行修改Q: 那如何修改Viewer源代码?我有扩展原生逻辑的需求。A: 可以使用Piggyback的方式,即在自己的逻辑中动态的替换、扩展Viewer自身的函数Q: 针对离线加载模型的场景,如何有效的提取Viewer可读的模型文件(SVF)到本地?A: 可以通过我们搭建的Extractor应用提取:https://extract.autodesk.io/,亦可自行部署该应用:https://github.com/cyrillef/e…