草庐IT

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

coder 2023-08-07 原文

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

对于特定的图像大小,这可以很好地工作。

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

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

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

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

更新 1:

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

这是一个 jsfiddle,它演示了在使用 toDataURL 处理较大的 Canvas 时 anchor href 下载链接如何失败,但 toBlob 似乎有效:

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

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

Data protocol URL size limitations

最佳答案

不,似乎没有任何事件让您知道是否带有 download 的 anchor 属性实际下载资源成功。

但是,您面临的限制似乎只涉及这种情况: anchor 元素 <a>download属性。

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

这很重要,因为它允许您将此 dataURI 转换为 blob,然后创建一个 object URL 从这个 Blob 。 object URL的 URI 很小,在带有 download 的 anchor 中不会遇到这种长度限制。属性。

所以在你的情况下最好的可能是直接使用 canvas.toBlob方法 ( a polyfill is available on mdn ),并传递 object URL的 URI 作为 href你的 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 ] (因为 download 属性被 SE-Snippets 中的某些 UA 阻止)

但请注意,即使 object URL 的字符串表示形式 (URI)简而言之,它实际上会占用浏览器内存中文件的大小,直到您硬刷新页面(清除缓存)或关闭您创建此对象 URL 的选项卡。所以你绝对需要调用URL.revokeObjectURL()清除这个空间。
但是,由于没有事件可以知道下载是否真的成功了,所以你只能使用 onclick 了。事件,它将在文件下载发生之前 触发。根据我的测试,等待带有 requestAnimationFrame 的单帧足够了,但我可能错了。


对于那些使用其他来源而不是 dataURI Canvas 的人来说,SO 中已经有很多关于将 dataURI 转换为 blob 的帖子,你可以检查上面提供的 mdn polyfill,他们'我也在做。

关于javascript - 是否可以以编程方式检测数据 url 的大小限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36918075/

有关javascript - 是否可以以编程方式检测数据 url 的大小限制?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  3. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  4. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  5. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  6. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  7. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

  8. ruby-on-rails - rails : save file from URL and save it to Amazon S3 - 2

    从给定URL下载文件并立即将其上传到AmazonS3的更直接的方法是什么(+将有关文件的一些信息保存到数据库中,例如名称、大小等)?现在,我既不使用Paperclip,也不使用Carrierwave。谢谢 最佳答案 简单明了:require'open-uri'require's3'amazon=S3::Service.new(access_key_id:'KEY',secret_access_key:'KEY')bucket=amazon.buckets.find('image_storage')url='http://www.ex

  9. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  10. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

随机推荐