精华内容
下载资源
问答
  • 问题导航,按需跳转背景Canvas绘制图片流程流程失败原因关于crossOrigin属性流程通了但是。。。设置crossOrigin属性后图片跨域无法加载服务器配置响应头缓存会导致跨域?突然想起想和大家说 背景 开发项目过程中遇到...

    背景

    开发项目过程中遇到一个问题,H5端使用canvas绘制合成图片并导出上传,在微信开发者工具上调试,流程完美通过无不良反应,绘制的canvas能正常导出合成的图片,心中一片祥和,想着终于能下班吃饭了,然而拿到Chrome浏览器一测试,流程居然跑不通了,完了饭又吃不上了,那就继续解决问题呗。

    Canvas绘制图片流程

    简单说一下我在canvas上绘制图片的过程(注意我是说我使用的方法,还有别的方法方式,全凭个人喜好):

    1. 因为用的图片是保存在阿里云oss服务器上面的图片,所以在页面上有个隐藏的容器放置需要用到的图片 img 标签,图片onload加载完成后绘制到canvas上才有效果,不然画上去也是空白的不用我说了吧,因此我是等到图片都触发onload后才调用绘制canvas的方法;
    2. 绘制图片时从Dom中获取到对应图片的 img 标签;
    3. 使用canvas的drawImage API把图片绘制到canvas上;
    4. 绘制方法执行完成后把这个canvas导出为图片,并上传到服务器,至此流程结束。

    流程失败原因

    为什么在微信开发者工具上面测试好好的,放到Chrome浏览器就不行了呢,F12打开调试一看,报错了:Failed to execute ‘toDataURL’ on ‘HTMLCanvasElement’: Tainted canvases may not be exported.
    报错信息
    凭借我小学水平的英语,我隐隐看出了这个错误的意思大概是:canvas无法执行toDataURL方法,受污染的画布无法输出。

    发现报错了第一时间肯定是复制粘贴到某度搜索一番,发现原来是受限于CORS 策略,会存在跨域问题,页面虽然可以使用跨域的图片(比如使用img标签或者append到页面上),因为浏览器本身不会有跨域问题,但是一旦绘制到canvas上就会污染这个canvas,导致无法提取到这个canvas的数据,也就无法输出了。

    前面忘说了项目的域名和图片服务器不是同一个域名,至于本地调试就更加不可能是同一域名了(不会有人打我脸吧,不会吧不会吧),而MDN上对使用其他域名下的图片是这样写的:
    MDN参考
    有解决方法一切都好说,那就给图片上 crossOrigin 属性!!!

    关于crossOrigin属性

    在这里插入图片描述
    以上是MDN的解释,自己理解过来就是:

    1. 加了 crossOrigin 属性,则表明图片就一定会按照 CORS 来请求图片。而通过CORS 请求到的图片可以再次被复用到 canvas 上进行绘制。换言之,如果不加 crossOrigin 属性的话,那么图片是不能再次被复用到 canvas 上去的。
    2. 可以设置的值有 anonymous 以及 use-credentials,2 个 value 的作用都是设置通过 CORS 来请求图片,区别在于 use-credentials 是加了证书的 CORS。
    3. 如果默认用户不进行任何设置,那么就不会发起 CORS 请求。但如果设置了除 anonymous 和 use-credentials 以外的其他值,包括空字串在内,默认会当作 anonymous来处理。

    流程通了但是。。。

    给图片上 crossOrigin 属性,无非就两种方式,一个是在HTML标签上设置 crossOrigin 属性,一种是用JavaScript获取到元素后设置 crossOrigin 属性,一开始我是用JavaScript去设置的,为什么说一开始用,别着急慢慢看完就知道了

    // 方式一,在img标签上直接添加crossOrigin属性
    <img src='图片src' id='img' crossOrigin='Anonymous' />
    
    // 方式二,获取img标签后添加crossOrigin属性
    let img = document.querySelector('#img')
    img.setAttribute("crossOrigin",'Anonymous')
    
    // 方式三,网上也有文章说两边同时添加crossOrigin的
    // 好像没有必要,但是试试也无所谓,万一呢
    <img src='图片src' id='img' crossOrigin='Anonymous' />
    ……
    let img = document.querySelector('#img')
    img.setAttribute("crossOrigin",'Anonymous')
    

    给图片设置完 crossOrigin 属性后再次测试,流程顺利执行完成了,生成的图片也能上传了,下班啦下班啦,我开始欢呼然后看了一眼服务器上的图片。

    “嘿,黑了”
    嗯?谁黑了???
    你想的没错是图片黑了,同时我的脸也黑了。
    上传图片直接是空白的,也不是空白,就是图片都绘制不上去,文字这些还是有的。

    设置crossOrigin属性后图片跨域无法加载

    设置完 crossOrigin 属性虽然流程能执行完,但是同时也报错了:Access to image at ‘网络图片路径’ from origin ‘本地调试端口’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
    报错信息
    这个错误就好理解,相信做前端的没谁没遇过这个问题(不会又有人打我脸吧,不会吧不会吧),大概意思就是跨域不允许访问呗,因为服务器的响应头里没有设置Access-Control-Allow-Origin或者设置的Access-Control-Allow-Origin不包含你的域名,因此不允许你跨域访问图片。

    虽然不会因此卡住流程不往下走,但同时绘制图片也空白了。

    把隐藏在页面的图片容器显示出来后发现图片加载失败了,细心的同学可能发现了上面我说过等图片加载完才调用绘制canvas的方法,为什么这里又说图片加载不了呢?

    这个就是我说的一开始用的JavaScript去设置 crossOrigin 属性,而HTML上面的 img 标签原本是没有设置 crossOrigin 属性的,因此页面初始化的时候图片能加载,但是到了绘制的时候重新设置这个 crossOrigin 属性的时候导致图片跨域了。

    这里需要注意的是:

    1. 使用 crossOrigin 属性,服务器必须加上响应头,否则客户端设置了 crossOrigin 属性也没用,会直接报跨域错误。
    2. 如果服务器已经设置了响应头还报跨域错误,那么就要考虑是不是缓存问题导致了。
      看过很多文章,有些文章有提到了缓存问题但是没给解决方案或者说不完善的解决方案,某种情况可用,其他情况又不可用;
      有些文章就是有人提了可用的解决方案但是没人说出是因为什么,也是心累。
    3. 所以这篇文章是对网上解决方案的一些总结,也是我费尽心思终于解决问题后的一点吐槽。

    服务器配置响应头

    关于服务器如何配置

    Access-Control-Allow-Origin: *
    

    如果服务器是自己搭建的,某度一下会有很多解决方案,这里就不在过多赘述了。

    如果是和我一样用的阿里云oss存储服务的话,那么去到oss的控制台,在跨域设置这里添加一个规则就可以了,这里提个注意的点,如果同时使用的CDN加速服务的话,那么CDN这里最好也同样设置一下,不然可能CDN的跨域规则会覆盖掉oss的,或者说出现的跨域问题是由CDN这里造成。
    在这里插入图片描述
    一般来说这里设置好,问题基本上都可以解决了,但是如果以上步骤都做了还是提示跨域错误,那么真相只有一个!!!就是缓存问题(打不了脸,相信我)

    缓存会导致跨域?

    缓存当然不会导致跨域,想啥呢。但是在我这里确确实实出现了,到底是为什么呢?

    在这里先上解决方案,就是网络图片路径后面加随机数或时间戳,没想到吧哈哈哈,原因后面再讲。
    这里给网络图片路径加随机数和时间戳的方式见仁见智,框架不同代码写法也不同,就不较真了,大家理解就行。

    // 方式一,推荐
    <img src='图片src?v=随机数或时间戳' id='img' crossOrigin='Anonymous' />
    
    // 方式二,在我的代码里面不推荐这种方式
    // 因为和我已有的逻辑冲突,图片onload完才绘制,绘制时重新加随机数又会重新触发onload,死循环
    // 大家结合代码逻辑选择喜欢的方案,记得图片onload完才绘制图片哦,上面说过了
    let img = document.querySelector('#img')
    img.src = '图片src' + '?v=' + Math.random()
    img.setAttribute("crossOrigin",'Anonymous')
    

    为什么加了随机数或者时间戳就又可以了呢?
    在这里卡了我很久,明明服务器也设置允许跨域了,为什么还是不行?
    冥思苦想了很久,想到某篇文章上面有人提了加随机数的解决方案,就试了一下,居然可以了!!!
    然后又想到某篇文章有人提过缓存问题(这篇文章说的解决方案是HTML img标签和JavaScript上都设置 crossOrigin 属性,我也试了但是没有用),突然思路就接上了。。。

    原因在于,虽然我有一个专门放置需要绘制的图片的容器,但在页面其他地方也同样会用到这些图片,我猜想是不是别的地方缓存了同样的图片。
    因为使用 img 标签加载的图片,浏览器默认会缓存起来(但我发现在我的代码里是图片加载完才调用绘制canvas的方法,因此同样会缓存,无论别的地方有没有用到),等到我使用JavaScript设置图片 crossOrigin 属性的时候,意味着图片将以 CORS 的方式请求,但缓存中的图片显然不是的,所以浏览器直接就拒绝了,连网络请求都没有发起,容器里面的图片也就变成了图片加载失败的样子了。
    图片加载失败
    在 Chrome 的调试器中,在 network 面板中,勾选了 disable cache 选项,验证了问题确实是因为缓存,浏览器这时发起了请求并且JavaScript的 img 也能正常请求到图片。

    所以后面我改用了方式一,在 img 标签上设置 crossOrigin 属性,再测试一切正常,终于可以下班了!!!

    突然想起

    一开始在微信开发者工具上面调试完全没问题,这就不禁让人想到,微信开发者工具对跨域这个问题上,有些过于宽松了,起码比移动端的微信浏览器都宽松,因为用真机测试同样会出现跨域,这不是坑害我们这些开发者吗,连在移动端微信浏览器的体验都不一致。手动狗头!!!

    想和大家说

    写博客的初衷呢,是把自己遇到的问题和值得分享的解决方法分享给大家,希望这篇文章可以帮到遇到同样问题的程序猿们。

    最后附上MDN关于canvas绘图的参考文献

    展开全文
  • 如何找到问题所在

    2011-07-08 14:26:10
    为了找到问题的根源,首先要确立一条:寻找因果联系,这样才能找到原因。相关性是不够的,只能作为猜测。我们的寻找过程就是,猜测加验证:如果验证了猜测的正确性,那么最好了;如果证伪,重新做一个猜测,继续验证...

    为了找到问题的根源,首先要确立一条:寻找因果联系,这样才能找到原因。相关性是不够的,只能作为猜测。

    我们的寻找过程就是,猜测加验证:如果验证了猜测的正确性,那么最好了;如果证伪,重新做一个猜测,继续验证。


    此外,有的时候同样的东西,别人是好的,你是不对的。
    如果两个人基于同样的信息(或数据)使用同样的逻辑(或工具),没道理得到不一样的结论/结果。
    这个时候真正感兴趣的是,是什么信息或者逻辑不一样,而不是具体结果如何。


    如果想清楚了问题,很多时候解决方案是很简单的,所谓思从深,行从简。


    展开全文
  • android内存泄露问题

    2016-01-19 11:16:03
    android的内存泄露问题,对这种问题进行分析和解释,让你更好的去寻找问题所在
  • 甚至我所在的组织里,对故障的分级也是对此参照的:如果是数据显示错误,则属于轻度故障;如果是数据更新错误,则属于严重故障。但查询并不总是善类,比如在《基于Oracle的SQL优化》一书中,作者曾提到一个案例:...

    在数据库中对数据的操作可以分为两类:查询和命令。由于命令会修改状态(数据),因此会得到开发团队很高的关注。甚至我所在的组织里,对故障的分级也是对此参照的:如果是数据显示错误,则属于轻度故障;如果是数据更新错误,则属于严重故障。但查询并不总是善类,比如在《基于Oracle的SQL优化》一书中,作者曾提到一个案例:优化一个关联了18个表的查询。在赞叹作者高超的SQL调优技术的同时,我不禁想到是否真有必要编写如此复杂的SQL?复杂查询带来可能不仅仅是性能问题,其背后隐藏的还有可能是不恰当的架构和设计。查询应该受到更多的关注。

    \

    控制条件查询的复杂度

    \

    企业应用程序的开发人员经常和数据库打交道,有时会过于依赖SQL强大的查询能力,随着需求的演化,SQL可能会越来越复杂,难以维护。

    \

    通用的条件查询

    \

    比如考虑一个酒店预订网站,客户在下单后的30分钟内需要完成支付或是提供信用卡担保,否则系统会自动将订单取消。开发团队使用定时任务来筛选出“过期”的订单:

    \

    09ced128b328479e2caeffe3ac619ac6.png

    \

    图表 1 使用SQL条件查询

    \

    看上去也挺简单,但是订单作为一个主要的业务对象,会有许多查询的需求,一般都会实现动态条件查询。

    \

    de5bcb056aff31dea5306f2dbb5f8a5d.png

    \

    图表 2 构造条件查询,要求orderRepository的实现能够动态拼接SQL语句

    \

    条件查询虽然好用,但测试起来可不轻松。因为在依赖数据库的自动化测试中准备、清理数据相比单元测试更麻烦。每个测试用例的上下文最好是独立的,这样不容易因为测试用例执行顺序问题导致测试结果不一致。此外,测试数据相互独立对于维护性也很重要,当测试用例达到一定规模时,“复用”测试数据以减小工作量的初衷是好的,但是很容易让测试用例的设计顾此失彼,适得其反。不必要的条件查询和其组合加剧了这个问题。另一方面,随着需求演化,有些查询条件还需要额外关联一些表,比如,现在要求VIP会员不受自动取消过期订单的约束。SQL可能变成了:

    \

    bbc4e23e094cb1799a0e8a688b53466e.png

    \

    图表 3 随着需求演化,SQL开始变得复杂

    \

    于是不断有新的条件和关联表被加进来,而测试时要准备的数据也越来越多。在实际项目的iBATIS sqlmap文件中(此处的例子都经过简化),改造前拼接动态查询的篇幅超过了200行,可以根据条件动态关联对应的表,貌似十分“强大”,实际上看起来都很费劲,添加新功能经常导致部分查询的条件拼接不完整,非常痛苦。

    \

    查询 “结果”

    \

    对于按客户名称搜索订单,还是条件查询比较好用。但对于特定目的,又带有计算的查询就不是那样了。实际上,我们可以把计算的结果用来实现查询,而不是在查询中去计算。开发团队为了解决这个问题,后来改造了下单的过程,计算并保存了订单的截止时间并为其实现了一个专用查询。

    \

    c87b02015a156c1a575662d61f8c2cb6.png

    \

    图表 4 保存计算的结果,计算在下单时完成,很容易做单元测试

    \

    0b07082528a9f26721d370657cfad734.png

    \

    图表 5 查询结果

    \

    随着设计的变化,测试策略也相应调整,现在由ApplicationEvents的单元测试来验证关键的业务条件,而查询可能过期订单的测试由于和订单这个“热门”隔离开了,测试的数据准备和清理不容易发生冲突,也变得更为简单。

    \

    慎用数据库集成

    \

    在实现修改状态的功能时,开发团队往往会定义良好的接口和服务契约来降低构件间的依赖。而在处理查询功能时,开发团队有时会迫不得已使用数据库集成,但这种方式却悄悄地削弱了解耦的努力。

    \

    数据来自于两个系统

    \

    让我们回到酒店预订网站的例子,现在希望提供住客点评酒店的功能。但为了防止“灌水”,要求对每张订单只能点评一次。

    \

    61f687bc1fc039f70b2da50574e69c9f.png

    \

    图表 6 订单中心可以点评

    \

    在系统实现上,酒店点评是独立于酒店订单的一个应用程序。如果只是在查看订单详情时才显示点评的入口,那么开发团队会很自然地想到通过应用程序集成,比如由酒店点评系统提供一个查询某张订单是否有对应点评的服务。不过若在订单列表就要显示的话,开发团队觉得还是直接使用数据库集成更简单一些,而且还减少通信次数。改造一下订单列表的查询语句,在其中嵌套点评计数的语句:

    \

    b9934b6cc0ac429981bd96409eaab9da.png

    \

    图表 7 数据库集成

    \

    查询“本地”数据

    \

    但很快,开发团队发现这也许不是一个明智的主意。一方面,这个方案会增加订单查询的持久化测试用例,而且为了能够部署流水线中运行这些测试,还不得不把本属于酒店点评系统的数据库脚本复制过来。而另一方面,开发团队发现这个方案其实要求两个系统合用一个数据库,或至少使用DBLink才行。这种部署灵活性上的缺陷也给部署流水线的准备带来了不少的麻烦。

    \

    7d44ddde033d42b11dec900a33c5fdd5.png

    \

    图表 8 部署限制

    \

    于是,团队调整策略,在t_hotel_res_order上增加了点评数量的冗余字段,而该数据采用消息队列来同步,这样查询就可以在“本地”实现了。

    \

    696612bea37ca3d441975c819e27d721.png

    \

    图表 9 使用MOM集成

    \

    Fail fast Learn fast

    \

    一般来说,一个功能总是可以通过多种方式来实现,除了性能之外,可维护性也是很重要的决策因素。开发团队的经验固然很重要,但尽早开展测试来评估、验证方案往往更科学。

    \

    参考实现方案对应的测试方案及成本:如果要为某个查询的测试用例准备5、6个表的数据,那么值得考虑一下是否有查询“结果”的方案。尤其是报表类的功能,非常容易演化成长篇的SQL语句。

    \

    参考实现方案对应的部署方案:尽早建立部署流水线,尽早规划部署资源和方案并演练。如果出现不必要的“限制或约束”,那么值得考虑更换集成方案。

    \

    感谢侯伯薇对本文的审校。

    \

    给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ)或者腾讯微博(@InfoQ)关注我们,并与我们的编辑和其他读者朋友交流。

    展开全文
  • 出现这个问题是因为,显示报表用的图片及js文件无法找到所造成的。它默认情况下会从 aspnet_client的站点寻找,它的物理路径C:\inetpub\wwwroot\aspnet_client\system_web\2_0_50727\crystalrepor...

           在用域用户登陆BusinessObjectEnterprise来读取报表时,在显示报表的时候会报错 ”bojo" 示定义。出现这个问题是因为,显示报表用的图片及js文件无法找到所造成的。

    它默认情况下会从 aspnet_client的站点寻找,它的物理路径

    C:\inetpub\wwwroot\aspnet_client\system_web\2_0_50727\crystalreportviewers12。

            确认把 aspnet_client设成站点

            确认把 aspnet_client目录下的文件的完整性

    转载于:https://www.cnblogs.com/cww2010/articles/1766060.html

    展开全文
  • 题目描述: ...解法二:一个数超过所在序列总数的50%,可以对所有数字进行一遍排序。中间数字就必然是要寻找的数字t。 没错当然!这种寻找方法相对于解法一,速度肯定是快了,我们知道若是用快速排
  • 第一种发生了错误 第二种正确,我没法现问题所在,有大佬能解释一下哪有问题? 完整的代码: ``` /** * Definition for a binary tree node. * struct TreeNode { * int val; * struct TreeNode ...
  • 他花了很长的时间去寻找问题的来源,但一直没有找到。之后,他跟我描述了他的问题。我提议帮他看看,然而得到他的回答是,他已经将代码还原到上一个版本了。也就是说,他放弃了寻找问题的来源。...
  • WPF下DispatcherTimer问题

    千次阅读 2010-11-15 17:25:00
    下面本来是要发在CSDN论坛里的问题,可视后来发现问题自己解决了,但是通过多次尝试,并没有重现问题,所以暂时把问题发这里,待后面再寻找问题所在。   ###问题###   WPF下...
  • 然后一层一层寻找问题所在。 感觉就像在玩侦探破案游戏一样,找到了问题并且解决是很有成就感的(我并不是QA哈哈) 记录一下自己出的bug 1、数据库 感觉数据库的问题,报错都挺明显的,只不过很长,注意看就行...
  • 使用VScode时格式化遇到的问题

    千次阅读 2018-09-14 20:25:36
    1.前言 ...双引号和分号都出来了,这不是更乱了么,于是,寻找问题所在,那是我们在使用vscode的插件vetur时使用了默认设置,那我们需要更改这个配置: (快速的解决办法)首先我们找到vetur的...
  • 使用nifi抽取数据但是到了executesql组件的时候需要等老久,于是把生成的sql拿出来去数据库可视化工具里面执行然后跑起来去干别的忘了,等过了半个小时还没跑完,于是乎开始寻找问题所在。 一开始看着报错是ORA-...
  • 其实很久之前就想写一个专题就是把工作中遇到的问题收集起来,然后解决方案也提供下,奈何太懒,今天开始就逐一收集,把这个习惯保持下去。 问题起因是这样,这个问题来源于同事,同事需要做一个读写...于是开始寻找...
  • 这个命令来逐层寻找比较大没用的文件。通过删除这些没用的文件来释放磁盘的空间。我这边通过检查发现/var/temp,/var/log目录的文件比较大,由于这两个文件都是一些临时和日志文件,对我来说没什么用,所以把这两个...
  • 在windows环境下演示死锁,以及排查,寻找问题所在(linux下思路一致,只是命令不一样而已) 1.找到对应程序项目运行的pid(本人windows main方法,所以tasklist | findstr "java" 找所有的java相关) linux下使用...
  • 在开发《iPai图片批处理》软件过程中,我用GDIplus在PictureBox中DrawImage的方法处理图像。所得到的图片尺寸总是比设定的尺寸小... 于是继续寻找问题所在,原来PictureBox用的默认设置,3D外形,Fixed Single边界。试
  • 它主要是向读者阐述了一些关于问题定义和看待问题的方式方法,帮助读者解放自己的思维禁锢,多方面的去寻找问题的定义,并解决问题。  这本书分六篇列举了20个故事。以它极其幽默的方式让读者去接收作者的思维和...
  • CCF NOI1047 寻找鞍点

    千次阅读 2017-04-25 02:05:49
    问题链接:CCF NOI1047 寻找鞍点。 时间限制: 1000 ms 空间限制: 262144 KB 题目描述  给定一个5*5的矩阵,每行只有一个最大值,每列只有一个最小值,寻找这个矩阵的鞍点。鞍点指的是矩阵中的一个元素,它是...
  • 问题:像这样: 这个window打开的时候。这个form面里的验证息信居然示显到别的地方啦。而且 每日一道理 翻开早已发黄的页张,试着寻找过去所留下的点点滴滴的足迹。多年前的好友似乎现在看来已变得陌生,...
  • LeetCode162.寻找峰值

    2019-12-13 21:59:57
    问题寻找峰值:峰值元素是指其值大于左右相邻值的元素。 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。 数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。 ...
  • 最近在重写易语言模块的时候,在取子文本操作时老是出错,经常出现一些奇怪的问题,一开始以为是代码问题,可是找半天硬是找不到问题所在。 于是进入了找bug模式,这么几行代码,看了我半个小时,左改右改,总感觉...
  • 寻找二维数组的鞍点

    2011-09-07 11:35:36
    问题阐述:寻找二维数组的鞍点(即元素所在行值最大,所在列值又最小)   代码清单: public class FindSaddlePoint { public static void findSaddlePoint(int[][] array) { boolean flag = true; // ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 766
精华内容 306
关键字:

寻找问题所在