编程语言
首页 > 编程语言> > javascript – 是否可以以编程方式检测数据URL的大小限制?

javascript – 是否可以以编程方式检测数据URL的大小限制?

作者:互联网

我正在使用javascript和html画布来调整jpeg图像的大小.调整大小后,我使用canvas.toDataURL作为锚标记中的href属性,以便提供用户可以下载已调整大小的图像的链接.

这可以很好地达到某个图像大小.

似乎不同的浏览器对数据网址的大小有不同的限制,如下所述:
https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs

在chrome中,当我超过数据URL大小限制时,单击下载链接时没有任何反应;没有错误或任何事情(据我所知).

有没有办法以编程方式检测数据网址是否过大?也许某些浏览器事件会告诉我点击下载链接是否失败?

理想情况下,我想检测下载是否成功.当数据网址过大时,我想向最终用户显示一个解释,说明如何右键单击图像并选择“另存为…”,这似乎总是有效.

更新1:

看起来像使用canvas.toBlob是目前最好的解决方法.这是api文档:https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob.

这是一个jsfiddle,演示了当使用toDataURL更大的画布时锚点href下载链接失败,但toBlob似乎工作:

https://jsfiddle.net/upgradingdave/c76q34ac/3/

以下是一些相关的stackoverflow问题:
canvas.toDataURL() download size limit

Data protocol URL size limitations

解决方法:

不,似乎没有任何事件让您知道具有下载属性的锚是否实际上成功下载了资源.

但是,您所面临的限制似乎只涉及这种情况:锚元素< a>使用下载属性.

浏览器可以处理更长的dataURI(我认为在大多数浏览器中,限制与字符串长度的限制相同).例如,它可以将其加载到< img>元素,更重要的是在你的情况下,它可以处理dataURI字符串.

这很重要,因为它允许您将此dataURI转换为blob,然后从此blob创建object URL.对象URL的URI很小,并且在具有download属性的锚点中不会遇到此长度限制.

因此,最好的情况可能是直接使用canvas.toBlob方法(a polyfill is available on mdn),并将对象URL的URI作为锚点的href传递.

var img = new Image();
img.crossOrigin = "anonymous";

img.onload = function(){
  var ctx = document.createElement('canvas').getContext('2d');
  ctx.canvas.width = this.width*10;
  ctx.canvas.height = this.height*10;
  ctx.drawImage(this,0,0,ctx.canvas.width, ctx.canvas.height);
  // convert our canvas to a png blob 
  //  (for type use the second parameter, third is for quality if type is image/jpeg or image/webp)
  ctx.canvas.toBlob(function(blob){
     myAnchor.href = URL.createObjectURL(blob);
    });
  // since we are dealing with use files, we absolutely need to revoke the ObjectURL as soon as possible
  var revokeURL = function(){
    // but we have to wait that the browser actually prepared the file to download
    requestAnimationFrame(function(){
      // we've waited one frame, it's seems to be enough
      URL.revokeObjectURL(this.href);
      this.href=null;
      });
    this.removeEventListener('click', revokeURL);
    };

  myAnchor.addEventListener('click', revokeURL);
  };

img.src = 'http://lorempixel.com/200/200/';
<a id="myAnchor" download="anAwesomeImage.png">download</a>

[ Live Demo ](因为SE-Snippets中的某些UA阻止了下载属性)

但请注意,即使对象URL的字符串表示形式(URI)很短,它实际上也会占用浏览器内存中文件的大小,因此直到您对页面进行硬刷新(清除缓存)或关闭选项卡所在的位置.您创建了此对象URL.所以你绝对需要调用URL.revokeObjectURL()来清除这个空间.
但是,由于没有事件可以确定下载是否实际成功,因此您将遇到onclick事件,该事件将在文件下载发生之前触发.从我的测试中,使用requestAnimationFrame等待单帧就足够了,但我可能错了.

对于那些使用其他来源而不是画布来获取dataURI的人来说,已经有很多关于将dataURI转换为blob的帖子,你可以查看上面提供的mdn polyfill,他们正在这样做太.

标签:javascript,html5,canvas,todataurl
来源: https://codeday.me/bug/20190917/1809490.html