js 移动端通过createObjectURL生成的http连接打不开

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js 移动端通过createObjectURL生成的http连接打不开相关的知识,希望对你有一定的参考价值。

代码如下
var tempFile = dataURLtoFile(header+value['fields']['file']['data'],'tempFile');
var ul = window.URL.createObjectURL(tempFile);
location.href =ul;
//window.open(ul);
在PC端是可以打开这个url的 但是在手机端就不可以,location.href根本不跳转

参考技术A

    是不是缓存(估计不是)这样试试

    window.location.href = ul+'?time='+((new Date()).getTime());

    试试reload

    window.location.reload(ul+'?time='+((new Date()).getTime()));

    网上看见个解决办法

在移动web中,经常会使用window.location.href去跳转页面,这个方法在绝大多数浏览器中都不会存在问题,但是在安卓手机的微信自带浏览器中,会出现一个奇怪的bug
window.location.href = baseUrl + 'article/comment';
上面的代码是通过href属性赋值去跳转到文章的评论页面,这段代码在安卓手机的微信自带浏览器中会偶发性的失效,调用上面的代码后,浏览器进度条加载完后,页面并没有跳转,还是停留在当前页面。
暂时还没找到具体的原因,但是当时遇到问题时,感觉是缓存在捣乱,所以尝试着给跳转链接后面加了一个随机数或者时间戳,结果是问题解决了。
window.location.href = baseUrl + 'article/comment?v='+(new Date().getTime());
window.location.href = baseUrl + 'article/comment?v='+Math.random();


作者:胖芮
链接:https://www.jianshu.com/p/d1cfc2584301
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

参考技术B 可能是不支持手机端吧。

移动端图片操作——预览旋转合成

在上一节中已经提到了预览,预览可以通过data: URL格式或URL对象。

var file = upload.files[0];
//URL对象
var url = URL.createObjectURL(file);
var img = new Image();
img.style.width = ‘100%‘;
img.src = url;
img.onload = function(e) {
  window.URL.revokeObjectURL(this.src); //销毁
}
//data:URL格式
var img = new Image();
img.style.width = ‘100%‘;
var reader = new FileReader();
reader.onload = function() {
  img.src = this.result;
};
reader.readAsDataURL(file);

一切都很顺利,但其实有很多的坑,需要慢慢讲来。先从前面做的一个小功能说起。

这个小功能就是将两张图片合成起来,组成一张新的图片

 

一、技术实现

1)上传的控件就用“input[type=file]”实现

Android的webview不支持此控件,怪不得按钮怎么按都按不动,后面只得用客户端提供的接口做上传

期间发现UC浏览器会自动将上传控件包装成三个按钮的样子,只需设置为“opacity:0;”即可。

技术分享

2)使用“FileReader”,通过方法readAsDataURL获取data URL格式的图片内容,赋值给image。

IOS在上传图片或拍照的时候,显示出来的宽高是反的,这个时候我们增加了一步旋转的操作,让用户自己来控制。

在给image赋src值的同时,赋“crossOrigin”的值,用于后面的图片跨域

3)将图片画在“canvas”上,旋转其实也就是转这个canvas。通过计算坐标和角度实现旋转

4)将旋转后的“canvas”与剩下的两张文字图片,通过一个新的“canvas”合并到一起。

在将两个“canvas”画在一起后,发现通过webview上传的图片,不能使用“toDataURL()”方法了,这是因为画布被污染,第一个画布中的图片是跨域的。

5)最后将data URL格式的内容上传到服务器中保存。

总共开发时间是3天,在这个过程中有过几次技术推翻重做或者逻辑重整,兼容性方面也还有很大问题,包括图片的宽高的自适应等,还很不完善。

下图是最终效果,挑了张松狮的写真照:

技术分享

 

二、预览

原先我在做的时候,第2步和第3布是合在一起的,也就是图片显示出来的时候,已经校准好位置。

只是在实现的过程中碰到了很多麻烦,并且时间仓促,BUG修复起来比较费时,只得分两步。

先说说原先的过程

1)IOS图片上传或拍照,宽高相反

我用的是Android手机,刚开始并没有发现这个问题,后面别人帮忙测试的时候,才发现了这个重大问题,接下来就是折腾这个事儿,想要自动校正方向。

1. 通过exif.js获取图片元数据,通过获取“Orientation”属性判断方向【我的Android机中这个属性为undefined,IOS有值】,总共有8个值

技术分享  技术分享

左边是说明,右边是展示。表格中带“*”的是指翻转过来了。

接下来就是做计算,网上有很多计算方式,对于“>IOS7”的系统,计算逻辑可以参考下localResizeIMG插件195行

顺便说下,这个插件使用到了gulp的开发方式,如果要调试就要配置相关代码,可以参考《前端自动化构建工具gulp记录

插件中还大量使用了Promises/A+规范,关于这个规范可以参考《JavaScript中Promises/A+规范的实现

exif.getData(typeof file === ‘object‘ ? file : img, function() {
  orientation = exif.getTag(this, "Orientation");
  //计算逻辑....
});

 

2. “<=IOS7”系统的计算方式略有不同。IOS6中图片拍照上传会被压扁(当照片超过2M时),这是IOS6的BUG,较大的图片可能会发生。

计算逻辑也可以参考localResizeIMG插件165行。要解决这个BUG需要引入megapix-image.js

require([‘megapix-image‘], function(MegaPixImage) {
  var mpImg = new MegaPixImage(img);
  //计算逻辑
});

技术分享

 

2)将画布“canvas”通过方法“toDataURL”,变成data URL格式

1. 在手机QQ浏览器中,canvas对象使用toDataURL方法获取不到任何数据,需要引用jpeg-encoder.js解决。

var cvs = document.createElement(‘canvas‘);
var ctx = cvs.getContext("2d");
ctx.drawImage(theImg, 0, 0);
var theImgData = ctx.getImageData(0, 0, cvs.width, cvs.height);
// Encode the image and get a URI back, toRaw is false by default
var jpegURI = encoder.encode(theImgData, quality);

 

在开发的时候方向自动旋转花了很多时间。碰到各种问题,例如“orientation”属性获取不到、自动旋转的角度不对。

后面贪简单,就找了个canvasResize插件,虽然会自动校正,但是图片有点模糊,而且图片的宽高不容易控制。效果不尽如意,只好分两步做。

最终的过程

1)添加旋转页面

先计算起始坐标点X与Y,简单点就是宽度和高度各除以2,再通过canvas的“translate”,再用“rotate”计算角度。在“drawImage”的时候X和Y点变成负数,移位过去。

var xpos = canvas_width / 2;
var ypos = canvas_height / 2;
ctx.translate(xpos, ypos);
ctx.rotate(angle * Math.PI / 180);
ctx.drawImage(rotate_img, -width / 2, -height / 2, width, height);

技术分享

 

三、合成

在上图中点击确认就会自动合成。

1)图片宽高自适应

画布的宽高只做了简单的比率,画布的宽度除以图片的宽度,我把头部的图片和底部的图片宽度都做的相同,下图所示:

技术分享  技术分享

var multiple = width / header.width;//画布宽度除以图片宽度

var header_height = header.height * multiple;//顶部图片
var footer_height = footer.height * multiple;//底部图片
var footer_y = canvas_height - footer_height;

 

2)将顶部与底部图片、与上一个旋转后的canvas画一起在第二个画布上

ctx.drawImage(rotate_canvas, 0, 0, width, height);
ctx.drawImage(header, 0, 25, width, header_height);
ctx.drawImage(footer, 0, footer_y, width, footer_height);

这里碰到了一个画布污染的问题。上面的“rotate_canvas”,图片的获取有两种,一个是通过“file”控件上传的,另一个是在webview提供的接口上传的。

两个唯一的不同是跨域,第二个接口返回的是另外一个域名中的图片。图片跨域了,那么rotate_canvas也算是跨域了。

跨域的话,会影响“toDataURL()”方法。这个时候就需要img图片跨域。

1. 图片设置crossOrigin属性,这是一个HTML5属性,兼容性不是很好,测试了几台Android机,有的行,有的不行。

rotate_img.crossOrigin = "Anonymous";

2. 服务器需要设置,可以正确响应 Access-Control-Allow-Origin 头。

调试的时候,如果服务器还没配置,可以用Fiddler模拟响应头。

a. 先找到filter选项

技术分享

 

b. 设置请求头

技术分享

 

c. 设置响应头,注意与请求头中的内容要一模一样,少个“http”都不行

技术分享

 

 

参考资料:

http://tgideas.qq.com/webplat/info/news_version3/804/808/811/m579/201409/278736.shtml   H5拍照应用开发经历的那些坑儿

https://imququ.com/post/how-to-auto-rotate-photo-in-js.html   图片自动旋转的前端实现方案

http://www.impulseadventure.com/photo/exif-orientation.html     JPEG Rotation and EXIF Orientation

http://blog.csdn.net/linlzk/article/details/48652635     利用exif.js解决ios手机上传竖拍照片旋转90度问题

http://www.slideshare.net/99leon/html5-create-thumbnail  Html5 create thumbnail

以上是关于js 移动端通过createObjectURL生成的http连接打不开的主要内容,如果未能解决你的问题,请参考以下文章

移动端图片操作——预览旋转合成

通过createObjectURL实现图片预览

移动端自动生成 meta js

将 createObjectURL 的结果分配给图像无法在移动 Safari 上加载资源

sdk-3.1.1.js:1 未捕获类型错误:无法在“URL”上执行“createObjectURL”:未找到与提供的签名匹配的函数

js图片前端预览之 filereader 和 window.URL.createObjectURL