在微信中调用外部浏览器实现文件下载之解决
写在前面,2017.11.10记:很多朋友反馈文章中的方法不行了,笔者试了一下确实有问题,应该是微信后期升级调整了下载策略导致的。其实最简单的方法就是引导用户让其自己从外部浏览器打开,比如当他点击下载时判断下他是不是在微信环境中(js很容易判断),如果是在微信环境中,弹出一个提示让其点击右上角,选择从外部浏览器打开。下文大家可以略过了。
笔者做的项目中多数都带有app客户端,我们一般会在web项目首页做个二维码,然后用户用手机扫一扫就能下载了。但是很多用户反映扫一扫之后下载不了,了解之后才知道这些用户都是使用的微信的扫一扫,而我们开发测试人员一般使用uc之类的浏览器做扫描。上网查了一下,微信自带的内置浏览器屏蔽了下载功能,所以才出现用微信扫一扫不能下载的情况。这时候我们一般会建议用户使用uc或者其他第三方浏览器自带的扫一扫功能下载。
但是现在的微信太普及了,很多人都习惯性的使用微信来扫码下载,总不能每个用户都解释一遍,所以我们一直在寻找解决方案。
要解决这个问题思路很明确,既然微信内置浏览器不支持下载,那就只能想办法调用外部浏览器来下载。所以我们在寻找这么一种方案:点了某个链接后能自动调用打开外部浏览器的功能,而不是让用户自己手动点击微信右上角的打开浏览器。
好了,废话不多说了,直接上方案,方法其实很简单,那就是使用直链。比如将你的下载链接定义为http://www.XXX.com/123.doc,这样用户在微信中点击这个链接的时候就会自动触发打开外部浏览器的功能。事实上,腾讯官方的QQ下载就是这么实现的。
我们之前的下载链接都不是直链,而是采用.do引导下载的方式,这种方式有个好处,那就是当我们发布新的app版本之后我们不需要改这个链接,do方法会自动找到最新版本进行下载。虽然这种方式也会向客户端打印数据流,但是微信内置浏览器目前似乎识别不出这是一个下载链接。所以如果目前你也在采用类似的方式,那么解决方案就比较明了了。
然而,采用直链后就ok了吗?非也!笔者在测试过程中发现并不是所有的直链都能诱发微信弹出外部浏览器选择窗口,比如这个直链就不行http://www.XXX.com/123.apk。为什么不行,不知道,不相信的话你可以试一下。但是这个直链就行http://www.XXX.com/123.doc,真的是很奇怪的事情。所以最终的解决方案是:充分利用一个可以诱发微信弹出外部浏览器选择窗口的直链!笔者尝试了两种办法,都可行,往下看。
方法一:利用过滤器
1.在你的根路径下放置一个内容为空的文件123.doc,保证通过http://www.XXX.com/123.doc能访问到。
2.将你的下载链接这么写:
<a href="http://www.XXX.com/123.doc">下载app</a>
3.创建一个过滤器:
package com; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @SuppressWarnings("unchecked") public class DlFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; String url = ""; String ua = request.getHeader("user-agent");// http头信息; if(ua.indexOf("MicroMessenger")!=-1){//从微信中过来的请求 chain.doFilter(req, res); //继续往下走,诱发微信弹出外部浏览器选择窗口 }else{//来自微信外部浏览器 url = "123.apk";//或者其他可以下载到你附件的链接,.do的也可以啊 response.sendRedirect(request.getContextPath()+url); } } /** * 初始化 */ public void init(FilterConfig fc) throws ServletException { } }
4.在web.xml中注册你的过滤器
<!-- 下载客户端 --> <filter> <filter-name>DownFilter</filter-name> <filter-class>com.DlFilter</filter-class> </filter> <filter-mapping> <filter-name>DownFilter</filter-name> <url-pattern>/123.doc</url-pattern> </filter-mapping>
这种方法的思路是,当用户点击http://www.XXX.com/123.doc的时候,请求先被过滤器捕获,然后在过滤器中判断请求是来自微信还是非微信,如果是来自微信就让请求继续往下走,这时候微信会认为你是在下载文件,会弹出外部浏览器选择窗口;当用户使用外部浏览器打开http://www.XXX.com/123.doc后,还是先被过滤器捕获,过滤器发现请求不是来自微信,那好,把请求重定向到真正的文件下载上。
方法二:do方法引导下载
1.还是在你的根路径下放置一个内容为空的文件123.doc,保证通过http://www.XXX.com/123.doc能访问到,因为咱们要充分利用它吗。
2.将你的下载链接这么写:
<a href="http://www.XXX.com/dl.do">下载app</a>
3.在方法中先判断请求来自哪里,判断方法跟上面一样,如果发现请求是来自微信,那么将请求内部跳转到文件上,注意是内部跳转,不能重定向外部跳转,如果使用重定向跳转,那么你的链接地址就变了,当你用外部浏览器打开后你下载的就真的是doc文件了。所以务必使用内部跳转,这样的话地址不变,当你用外部浏览器打开后访问的地址仍旧是http://www.XXX.com/dl.do,这样该方法再次被你的程序捕获,发现请求已经不是来自微信了,那样的话你就开始下载你真正的目标文件吧。
好了,亲们,上面两种办法笔者都尝试过了,均可行。如果你有更好的办法也请共享出来,方便广大码友。
多说一句,我发现网上有网友提了这么一个需求,那就是在微信中点击一个链接,这个链接就是个普通链接,希望用户点击完之后能自动在外部浏览器中打开,不想在微信中打开,如何实现?我上面提供的两种思路均能实现!
其实我个人更希望微信能提供一个js接口,能主动调用右上角菜单里面的打开外部浏览器功能,这样的话,我只要在链接上加一个onclick事件就ok了。不知道有没有,反正我没发现,有的话请知情人共享一下调用方法。
-
1微信开发errcode:45015,errmsg:response out of time limit之完美解决
-
2archive is not a ZIP archive之解决
-
3火狐每次启动都弹出迅雷提示下载openh264之解决
-
4Eclipse中提示Could not find the main class之解决
-
5以小米6为例图说安卓手机如何安装谷歌四件套
-
6在微信中调用外部浏览器实现文件下载之解决
-
7java web项目代码不报错但是项目左上角有个红叉之解决
-
8Eclipse中svn资源库中文路径乱码解决
-
9万能方法用指定浏览器打开桌面上的网页快捷方式
-
10论坛注册:用户名包含被系统屏蔽的字符之完美解决
-
1微信开发errcode:45015,errmsg:response out of time limit之完美解决
-
2archive is not a ZIP archive之解决
-
3火狐每次启动都弹出迅雷提示下载openh264之解决
-
4Eclipse中提示Could not find the main class之解决
-
5XML document structures must start and end within the same entity报错解决
-
6以小米6为例图说安卓手机如何安装谷歌四件套
-
7在微信中调用外部浏览器实现文件下载之解决
-
8U盘安装CentOS 7终极方案,简单有效
-
9POI合并单元格时CellRangeAddress类提示过时之解决
-
10java web项目代码不报错但是项目左上角有个红叉之解决