是否可以通过编程检测数据url的大小限制? [英] Is it possible to programmatically detect size limit for data url?
问题描述
我使用javascript和html canvas来调整jpeg图片的大小。调整大小后,我使用 canvas.toDataURL
作为锚标记中的href属性,以提供一个链接,用户可以下载调整大小的图像。
I'm using javascript and html canvas to resize jpeg images. After resizing, I use canvas.toDataURL
as the href attribute in an anchor tag in order to provide a link where users can download the resized images.
这样可以达到一定的图片大小。
This works nicely up to a certain image size.
似乎不同的浏览器对数据网址的大小有不同的限制,如下所示:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/data_URIs
It seems that different browsers have different limits on the size of data urls as mentioned here: https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs
在chrome中,当我超过数据url大小限制,当我点击下载链接没有任何反应;没有错误或任何东西(只要我能告诉)。
In chrome, when I'm over the data url size limit, nothing happens when I click on the download link; no errors or anything (as far as I can tell).
有没有办法以编程方式检测数据网址是否太大?也许某些浏览器事件会告诉我是否点击下载链接失败了?
Is there a some way to programmatically detect whether a data url is too large? Maybe some browser event that will show me whether clicking a download link failed?
理想情况下,我想检测下载是否成功。当数据网址太大时,我想向最终用户显示一个说明,描述如何右键单击该图像并选择另存为...,这似乎总是工作。
Ideally, I'd like to detect whether the download was successful. When data urls are too large, I'd like to display an explanation to the end user describing how to right click on the image and choose "save as ...", which always seems to work.
更新1:
看起来像使用 canvas.toBlob
是现在最好的解决方法。以下是api文档: https://developer.mozilla.org/ en-US / docs / Web / API / HTMLCanvasElement / toBlob 。
It looks like using canvas.toBlob
is the best workaround for now. Here's the api documentation: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob.
下面是一个jsfiddle,演示当使用 toDataURL
来显示较大的Canvase时, $ c> toBlob 似乎有效:
Here's a jsfiddle that demonstrates how anchor href download links fail when using toDataURL
for larger canvases, but toBlob
seems to work:
https://jsfiddle.net/upgradingdave/c76q34ac/3/
以下是一些相关的stackoverflow问题:
canvas.toDataURL()下载大小限制
Here are some related stackoverflow questions: canvas.toDataURL() download size limit
推荐答案
不,似乎没有任何事件让你知道如果锚的下载
属性实际上成功下载资源。
No, there doesn't seem to be any event letting you know if an anchor with the download
attribute actually succeeded to download the resource.
但是,你面临的限制似乎只关注这种情况:锚元素< a>
与下载
属性。
But, the limitation you are facing seems to only concern this situation : an anchor element <a>
with the download
attribute.
浏览器可以处理更长的dataURI(我认为在大多数浏览器中,限制与字符串长度的限制相同)。例如,它可以加载到< img>
元素,更重要的是,在您的情况下,它可以处理dataURI字符串。
The browser can handle way longer dataURI (I think that in most browsers the limitation is the same as the one for strings length). E.g, it can load it to <img>
element, and more importantly in your case, it can process the dataURI string.
这很重要,因为它允许您将此数据URL转换为blob,然后创建 对象URL
。 对象URL
的URI很小,并且在下载
属性的锚点中不会遇到此长度限制。
This is important because it allows you to convert this dataURI to a blob, then to create an object URL
from this blob. object URL
's URI are small and don't face this length limitation in anchors with download
attribute.
所以最好的情况是直接使用 canvas.toBlob
方法( a polyfill在mdn 上可用,并将对象URL
的URI作为您的锚的 href
。
So the best in your case is probably to directly use the canvas.toBlob
method (a polyfill is available on mdn), and to pass the object URL
's URI as the href
of your anchor.
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代码段中的某些UA封锁)
[ Live Demo ] (since download
attribute is blocked by some UA in SE-Snippets)
但请注意,即使对象URL
的字符串表示(URI)很短,浏览器内存中文件的大小,直到您硬刷新页面(清除缓存),或关闭您创建此对象URL的选项卡。所以你绝对需要调用 URL.revokeObjectURL()
来清除这个空间。
但是,由于没有事件知道下载实际上已成功,您将被 onclick
事件阻塞,这将在之前触发文件下载。从我的测试中,等待一个框架 requestAnimationFrame
就足够了,但我可能错了。
But note that even if the string representation (URI) of the object URL
is short, it will actually take the size of your file in browser's memory, and so until you hard-refresh the page (clearing cache), or close the tab where you created this object URL. So you'll absolutely need to call URL.revokeObjectURL()
to clear this space.
But, since there is no event to know if the downloading actually succeeded, you're stuck with the onclick
event, which will fire before the file downloading occurred. From my tests, waiting for a single frame with requestAnimationFrame
is enough, but I may be wrong.
对于那些来自其他来源而不是一个帆布为他们的dataURI,已经有很多的文章SO转换一个数据URL到一个Blob,你可以检查mdn polyfill上面提供,他们也做。
And for the ones coming here with an other source than a canvas for their dataURI, there are already a lot of posts in SO about converting a dataURI to a blob, and you can just check the mdn polyfill provided above, they're doing it too.
这篇关于是否可以通过编程检测数据url的大小限制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!