微信内置的浏览器如何上传文件

作者:水歌
链接:https://www.zhihu.com/question/21452742/answer/34164634
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

以下是 网上搜索文档、团队实战经验的总结,主要基于 Android 4.0+、iOS 6.0+、微信 5.2+ ——
  1. 过去限制很多的 iOS 版微信 却没出什么大问题,反倒 Android 各版本的适配让我们各种加班
  2. 较新版本的微信并没有对 HTML 原生文件控件做限制,只是它默认调用 Android 系统自带的 WebView,限制是怎样的取决于相应版本 Android 的官方代码(有说法是出于安全考虑)
  3. 除了 Android v4.4.2 这个中间版本(小米 3、红米 Note 等机型的出厂系统),其它 v4.x 版本的 WebView 基本都可以使用 原生文件控件
  4. 若同机安装有 QQ浏览器,微信可以调用它修缮过的内核,就可以正常使用文件控件(但必须在安装 QQ浏览器之后重启微信才行)
  5. 如有某版本的 WebView 不能用文件控件,它的拦截是在底层进行的,所以 JavaScript 引擎层面并无异常抛出,不会中断程序的执行

再分享一段我手写的 Input File 图片友好版 v0.5 的代码( jQuery 插件)——
// -------------------------------------------------- //
//
//          >>>  Input-File 图片友好版  <<<
//
//
//    [Based on]    jQuery,  jQuery.Browser.js
//
//    [Version]     v0.5  (2015-7-3 14:26:30)
//
//
//        (C)2014-2015    test_32@fyscu.com
//
// -------------------------------------------------- //

(function (BOM, DOM, $) {

    var URL_Object = BOM.webkitURL || BOM.URL || BOM;

    $.fn.xImage = function (Type_Filter) {
        var $_This = this.find('*').addBack().filter('input[type="file"]');
        Type_Filter = Type_Filter || [ ];

        $_This.parent().css({
            position:    'relative',
            cursor:      'pointer'
        });
        $_This
            .css({
                position:     'absolute',
                'z-index':    999,
                opacity:      0
            })
            .each(function () {
                var $_This = $(this);
                var $_PreView = $_This.siblings('img, img.PreView').eq(0);
                if (! $_PreView.length)
                    $_PreView = $('<img />').before($_This);

                $_PreView.addClass('PreView').css({
                    display:          'inline-block',
                    'max-height':     $(top).height() * (1 / 3),
                    'max-width':      $(top).width() * (1 / 3)
                })
                    .on('Ready',  function () {
                        $_This.css({
                            top:       $_PreView.position().top,
                            left:      $_PreView.position().left,
                            width:     $_PreView.width(),
                            height:    $_PreView.height()
                        });
                    }).trigger('Ready').on('load',  function () {
                        $_PreView.trigger('Ready');
                    });
            })
            .data('clicks', 0).click(function () {
                var $_This = $(this);
                var Click_Times = $_This.data('clicks');

                if ($.browser.mobile && (++Click_Times > 3)) {
                    BOM.alert("您当前的浏览器无法在本页上传文件……");
                    return false;
                }
                $_This.data('clicks', Click_Times);
            })
            .change(function () {
                var $_This = $(this).data('clicks', 0);

                try {
                    var iFile = arguments[0].target.files[0];
                } catch (iError) {
                    BOM.alert([
                        "您当前 浏览器内核 较为古老,暂不支持【图片上传预览】……",
                        "建议更换为最新版 搜狗、猎豹、傲游 等双核浏览器~"
                    ].join("\n\n"));

                    $_This.show().siblings('img.PreView').remove();

                    return true;
                }

                var iType = iFile.type.split('/');
                if (iType[0] != 'image') {
                    BOM.alert("您所选的文件不是图片……");
                    return false;
                } else if ($.inArray(iType[1], Type_Filter) > -1) {
                    BOM.alert([
                        "此处不能上传", iType[1].toUpperCase(), "格式的图片!"
                    ].join(' '));
                    return false;
                }

                var iReader = new FileReader();
                iReader.onload = function () {
                    $_This.siblings().not('img.PreView, input[type="file"]').hide();

                    var $_PreView = $_This.siblings('img.PreView');
                    $_PreView[0].onload = function () {
                        URL_Object.revokeObjectURL(this.src);
                    };
                    $_PreView[0].src = URL_Object.createObjectURL(iFile);
                };
                iReader.readAsBinaryString(iFile);
            });

        return this;
    };

})(self,  self.document,  self.jQuery);
其对应的 HTML 结构是 ——
<form method="POST" action="./xxx">
    <div class="ImageBox">
        <input type="file" />
        <span>上传美照</span>
    </div>
    <button type="submit">完成</button>
</form>
<script>
    //  原生文件上传控件“图片友好化”,
    //  并排除一些服务器处理不了的格式
    $('.ImageBox').xImage(['psd', 'webp', 'bpg']);
</script>

对于 DOM/JS 层面实在无法直接支持文件控件的,有两种备用方案 ——
  1. 引导失败的用户在其微信公众平台的主界面消息框中发送图片消息,服务器端做好相应接口支持
  2. 指导用户下载安装 QQ浏览器并重启微信(微信内下载只有 腾讯应用宝的链接可正常使用,否则就只能再打开一个下载网页并引导用户在其它手机浏览器中打开它去下载)

【插件备注】
  若用户多次点开文件选择对话框,但都没选择文件时(即 Change 事件从未触发),本插件可能也会判断为“当前浏览器文件控件被屏蔽”。
<think>好的,我现在需要回答用户关于微信内置浏览器下载文件时是否支持跨域请求的问题。首先,我得理解用户的问题核心:他们想知道在微信内置浏览器中进行文件下载时,跨域请求是否被支持,以及可能遇到的问题和解决方法。 首先,我应该回顾已有的参考资料。用户提供了三个引用,都是关于微信内置浏览器中的跨域问题。引用[1]提到手机UC、微信和支付宝浏览器在AJAX跨域请求上有问题,而谷歌和火狐没问题。引用[2]指出在iPhone的微信浏览器中,跨域时无法获取cookie,而安卓则正常。引用[3]的解决方案是通过Nginx配置添加CORS头来解决跨域问题。 接下来,我需要将这些信息应用到文件下载的场景中。通常,文件下载可以通过多种方式实现,比如使用`<a>`标签的下载属性、window.location.href跳转,或者通过AJAX请求获取数据再触发下载。不同的方法在跨域处理上可能有差异。 根据浏览器的同源策略,跨域请求会被限制,但有些操作比如使用`<a>`标签直接导航到资源可能不受同源策略的限制,除非服务器设置了CORS头部。不过,如果下载需要携带认证信息(比如cookies或Authorization头),则可能需要服务器配置CORS,特别是Access-Control-Allow-Origin和Access-Control-Allow-Credentials。 微信内置浏览器基于X5内核,可能对某些CORS策略的支持与其他浏览器不同。根据引用[1]和[2],微信浏览器在处理AJAX跨域请求时存在问题,特别是在iPhone上可能无法获取cookie。因此,如果下载请求需要携带cookie或进行身份验证,可能会出现跨域问题。 此外,引用[3]提到在Nginx配置中添加CORS头可以解决跨域问题,这说明服务器端的配置是解决问题的关键。对于文件下载,如果服务器正确设置了CORS头,可能可以支持跨域请求。 总结下来,可能的回答结构是: 1. 微信内置浏览器对跨域请求的支持情况,尤其是在下载文件时。 2. 不同下载方式(如直接链接 vs AJAX)的差异。 3. 需要服务器正确配置CORS头部,特别是处理携带凭证的情况。 4. 针对iPhone微信浏览器的特殊问题,如cookie无法获取的解决方法。 5. 可能的解决方案和最佳实践。 接下来需要验证这些思路是否正确。例如,使用`<a>`标签的下载是否受CORS限制?根据MDN文档,如果下载资源触发的是导航而非AJAX请求,可能不需要预检请求,但服务器仍需允许跨域访问,否则可能被拦截。特别是如果下载需要验证信息,服务器必须正确设置CORS头。 另外,微信浏览器的X5内核可能存在一些限制,导致即使服务器配置正确,仍可能遇到问题,需要特定的配置或处理方式。例如引用[3]中的Nginx配置调整。 最后,整理这些信息,用中文清晰回答用户的问题,并引用提供的资料作为支持。</think>在微信内置浏览器中进行文件下载时,跨域请求的支持情况需分场景讨论: 1. **基础跨域支持** 微信内置浏览器(基于X5内核)对跨域请求的限制与标准浏览器类似,但存在以下差异: - 直接通过`<a>`标签或`window.location.href`触发的下载请求,若服务器未设置CORS头部,可能被拦截[^1] - 使用AJAX/Fetch请求下载文件时,需服务器明确配置`Access-Control-Allow-Origin`等响应头[^3] 2. **携带凭证的特殊情况** 若下载请求需要携带Cookie或认证信息(如`withCredentials: true`),必须满足: ```nginx add_header 'Access-Control-Allow-Origin' '具体域名'; add_header 'Access-Control-Allow-Credentials' 'true'; # 关键配置 ``` 但iPhone的微信浏览器曾出现无法获取跨域Cookie的问题,需通过服务端会话机制替代Cookie验证[^2] 3. **解决方案建议** - 服务端配置CORS白名单,同时设置`Access-Control-Expose-Headers`暴露自定义响应头 - 对文件下载接口采用非认证方式(如临时令牌URL)规避跨域限制 - 针对iOS微信浏览器问题,可通过URL重写将会话ID附加到下载链接参数中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值