É possível detectar programaticamente o limite de tamanho para o URL de dados?

Estou usando javascript e html canvas para resize imagens jpeg. Após o redimensionamento, uso canvas.toDataURL como o atributo href em uma tag de âncora para fornecer um link no qual os usuários podem baixar as imagens redimensionadas.

Isso funciona bem até um determinado tamanho de imagem.

Parece que navegadores diferentes têm limites diferentes no tamanho dos URLs de dados, conforme mencionado aqui: https://developer.mozilla.org/pt-BR/docs/Web/HTTP/data_URIs

No chrome, quando estou acima do limite de tamanho de URL dos dados, nada acontece quando clico no link de download; sem erros ou qualquer coisa (tanto quanto eu posso dizer).

Existe alguma maneira de detectar programaticamente se um URL de dados é muito grande? Talvez algum evento de navegador que mostre se houve um clique em um link de download falhou?

Idealmente, gostaria de detectar se o download foi bem-sucedido. Quando URLs de dados são muito grandes, eu gostaria de mostrar uma explicação para o usuário final descrevendo como clicar com o botão direito na imagem e escolher “salvar como …”, o que sempre parece funcionar.

Atualização 1:

Parece que o uso de canvas.toBlob é a melhor solução alternativa por enquanto. Aqui está a documentação da API: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob .

Aqui está um jsfiddle que demonstra como links de download href de âncora falham ao usar toDataURL para canvass maiores, mas toBlob parece funcionar:

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

Aqui estão algumas perguntas relacionadas ao stackoverflow: canvas.toDataURL () limite de tamanho do download

Limitações de tamanho de URL do protocolo de dados

Não, parece não haver nenhum evento informando se uma âncora com o atributo de download realmente conseguiu fazer o download do recurso.

Mas a limitação que você está enfrentando parece se referir apenas a essa situação: um elemento de âncora com o atributo de download .

O navegador pode manipular muito mais o dataURI (acho que na maioria dos navegadores a limitação é a mesma que para o comprimento de strings). Por exemplo, ele pode carregá-lo para o elemento e, mais importante, no seu caso, ele pode processar a string dataURI.

Isso é importante porque permite converter este dataURI em um blob e criar um object URL partir desse blob. O URI do object URL é pequeno e não enfrenta essa limitação de comprimento nas âncoras com o atributo de download .

Portanto, o melhor no seu caso é provavelmente usar diretamente o método canvas.toBlob ( um polyfill está disponível no mdn ) e passar o URI do object URL do object URL como href da sua âncora.

 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/'; 
 download 

[Demonstração ao vivo] (desde que o atributo de download é bloqueado por algum UA em SE-Snippets)

Mas note que, mesmo que a representação de string (URI) da object URL do object URL seja curta, ela realmente terá o tamanho do arquivo na memory do navegador, e assim até você atualizar a página com dificuldade (limpar cache) ou fechar a guia onde você criou este URL de object. Então, você precisará chamar o URL.revokeObjectURL() para limpar esse espaço.
Mas, como não há nenhum evento para saber se o download realmente foi bem-sucedido, você está preso ao evento onclick , que será triggersdo antes de o download do arquivo ocorrer. Dos meus testes, esperar por um único frame com requestAnimationFrame é suficiente, mas posso estar errado.


E para os que vêm aqui com uma outra fonte além de uma canvas para seu dataURI, já há muitos posts em SO sobre como converter um dataURI em um blob, e você pode apenas verificar o mdn polyfill fornecido acima, eles estão fazendo isso também.