FileReader() is unable to read large files
我正在使用以下方法在上载图像之前预览图像:
1 2 3 4 5 6 7 8 9 10 11
| $("#file").change(function() {
var reader = new FileReader();
reader.readAsArrayBuffer(this.files[0]);
var fileName = this.files[0].name;
var fileType = this.files[0].type;
alert(fileType)
reader.onloadend = function() {
var base64Image = btoa(String.fromCharCode.apply(null, new Uint8Array(this.result)));
// I show the image now and convert the data to base 64
}
} |
我注意到,当图像较大时,该方法将失败,并且无法预览图像。
我不确定问题是由于base64转换还是FileReader引起的。
是否有任何设置可以增加最大大小,还是可以解决?
这是在控制台中引发的错误消息:
Uncaught RangeError: Maximum call stack size exceeded
at FileReader.reader.onloadend
-
你得到什么错误?
-
@SLaks:在base64转换时中断。
-
你得到什么错误?
-
@SLaks:当文件很小(如50kb)时,它可以正常运行;当文件很大时,它无法完成该过程。
-
@Arrrr"它坏了"不是一个错误。就像去看医生并在他们问您有什么问题时回答"有伤感"一样。当"它无法完成该过程"时,究竟发生了什么?
-
@ceejayoz:我不确定您是否在开玩笑,但我认为您确实知道" It Breaks"的意思是,它无法进行。 :)
-
@Arrrr不,您需要更具体。 Javascript控制台中有错误吗?
-
您如何显示图像?也许问题出在那部分。
-
@Barmar:用尽可能简单的话来说,当文件大时,什么也没发生。当文件大小小于100Kb时,它可以正常工作。
-
@Barmar:我删除了该部分并添加了alert进行测试,警报未显示,这与显示图像无关。
-
我不确定您是在开玩笑还是在开玩笑,但我认为您确实知道"您遇到什么错误"是什么意思。
-
您将收到一条错误消息,告诉您问题出在哪里。如果您未阅读错误消息,则不会找出问题所在。请注意,您可能会用捕获块或答应将其吞下。不要那样做。
-
@ SLaks:很清楚,大文件=不起作用,小文件=工作,您要我更具体吗???
-
我只是使用284,394字节的文件进行了尝试,在当前版本的Chrome中,它对我来说效果很好。
-
阅读错误消息!这不是"不起作用"。
-
@Arrrr尝试将这行var base64Image = btoa(String.fromCharCode.apply(null, new Uint8Array(this.result)));分解为单个变量。这将有助于缩小错误发生的位置。
-
@ kevin628:问题是大小!它不处理大文件,非常清晰,就像ASP.Net,WCF等中的MaxRequestLength。我想增加该大小!
-
FileReader的唯一大小限制是设备的内存。
-
@Arrrr考虑这些Google搜索结果是否对您有帮助。
-
@ kevin628:不,它没有
-
@Kaiido:Base64部分从一开始就存在。我需要数组而不是DataURL,我需要数组用于其他目的。
-
@Kaiido:使用AJAX将字符串发送到Web api,那部分就可以了。
-
"调用堆栈大小"并不意味着"文件大小"。问题是"偏离主题-缺少清晰的问题说明",现在是"超出最大调用堆栈大小"的副本
您的问题是使用Function.apply会将类型数组项转换为String.fromCharCode方法的参数。
函数具有最大参数长度限制。
为避免这种情况,处理大型文件时,最好的方法是根本不处理它。
如果需要将文件发送到服务器,只需直接发送Blob,这可以通过FormData API轻松实现。
如果需要在HTML媒体元素中显示文件,则使用URL.createObjectURL(yourFile)方法。
而且,如果您确实需要文件的dataURI版本,请使用reader.readAsDataURL(yourFile)方法。
sub>
-
抱歉,您不知道您的方法有多糟糕。检查我自己的答案。
-
@Arrrr,为什么?让我告诉你,readAsBinaryString已被弃用...如果仔细阅读我的回答,将会看到你不应该处理该文件
-
没关系,但是您的速度非常慢,并且有点疯狂。
-
我通过有效地解决对代码及其结构的影响最小化的问题。但是考虑你的...
-
您的速度仍然比reader.readAsDataURL慢,并且使用非标准和不推荐使用的功能并不是我所说的"有效方法"
-
当必须在服务器端对文件进行解码时,reader.readAsDataURI会导致问题。研究您将了解原因。
-
它包括不应该存在的东西,例如文件格式!我想你知道这个。而且,此方法可能已过时,但比您的方法快得多。
-
我的方法使用的是FormData API,您运行得更快,除了传输文件(而不是大30%的字符串...)之外,它对文件没有任何作用。
-
FormData无法以正确的格式序列化文件:)特别是IFormFIle。你知道ASP.Net Core吗?
-
@Arrrr,不,我不知道,但是我严重怀疑您是否无法访问通过多部分POST请求发送的文件...快速谷歌搜索使我认为您应该听Request.Form.Files;
-
无需潜入请求,可以使用[FromBody]属性:),在我看来,Internet Explorer已死,在开发网站时,我真的不在乎IE,甚至不针对该东西。 Edge支持了该方法,我刚刚进行了测试并且效果很好。
-
不赞成使用的方法的问题不是当前的实现,而是将来的实现...而且您仍在对文件进行无用的处理。但是我发现您很难摆脱您那些愚蠢的偏见,并且我不会再花更多的时间陪伴您。我只是希望一个乐于学习的人将来会读这个答案。
-
该处理有两个目的:1-显示文件的预览,2:在JSON模型中添加文件的base64版本。为什么??因为我可以在JSON模型中包含许多图像,然后在服务器端轻松地反序列化它们。为什么??因为文件上传是使用网络API实现的。为什么使用JSON模型,因为必须对主体进行反序列化,因为JS不知道不存在的HttpPostedFileBase或现有的IFromFile。
-
对于1使用URL.createObjectURL。对于2,您似乎在服务器端代码中拥有真正的流程,但是麻烦您了……我确实回答了您的问题:您面临的问题是apply引起的,而不是FileReader引起的。我还为您提供了最佳方法来实现您想要实现的目标。您不想尝试,我不能为您做更多。再见。
-
Kaiido,首先学习一些服务器端编程,然后再到这里,我们讨论为什么这种方式很好。
-
您的问题是关于FrontSide问题的。再读一遍。您唯一谈论服务器端的地方是侮辱性评论。我给了您一个答案,如果您在使用ASP.net处理文件上传时遇到问题,请提出一个新问题(但我确定已经存在很多骗子)。
-
好。我和平地问了这个问题,如果您读到评论,就看到其他人开始攻击,他们当然无济于事。而且您的方法肯定不是最佳方法!
-
在阅读这些注释时,我看到的是,您花了20多分钟才能理解我们需要阅读您的控制台报告的确切消息。没有这个,我找不到您真正的问题。您不能要求我们尝试重建您的应用程序,以使自己获得错误。
-
@Arrrr:将图像发送到以base64编码的服务器时,告诉某人学习服务器端编程是很讽刺的。使用多部分/表单数据进行有效的传输。是的,这是最好的方法。
-
@Ryan:我希望文件成为我的请求模型的一部分。无论如何,您确定我可以使用表单数据预览图像吗?您的观点是有限的,就大小而言,base64大于二进制数据,这意味着如果某人对在base64中传输二进制数据特别感兴趣,则一定有原因。我既不处理Form也不处理简单的上载器,但您的想法是如此简单,以至于看到讽刺意味:)
-
@Arrrr:Kalido也已经告诉您如何预览:使用URL.createObjectURL。没有理由您都必须使用相同的工具。
-
@Ryan:那么必须成为请求模型一部分的数据会发生什么呢?
-
@Ryan:如果您真的想检查文件是否是图像而不只是假冒扩展名,该怎么办?如果您想保护服务器免于虚拟请求怎么办?通过所有验证后,对文件进行Base64编码的缺点是什么?
-
@Arrrr:好的,如果您信任客户确认某件事实际上是图像,则您做错了。服务器必须检查。任何人都可以更改客户端。 base64不能神奇地使它更安全。
-
@Ryan:我不信任客户端,这就是为什么我要检查文件的原因:)我想实现自己的安全机制。我不希望任何不符合我的条件的请求都被发布。我需要知道第一个文件是什么,在上传可执行文件后,您会看到gmail阻止可执行文件,这很烦人,我想在需要时阻止上传。
-
@Ryan:"如果任何人都不能更改客户端,则可以防止更改客户端"。
-
我想事先阻止上传-好的,但是base64不能帮助您吗?
-
@Ryan:是的,Base64与安全性无关,但是您在客户端读取文件与此有关。我需要一个接受文件的强类型模型才能发送到我的Web API。不会涉及任何表格,因此您无法从请求中获取文件。此外,如果要编写通用文件处理程序API,则在请求中使用File数组,您将无法理解哪个文件是哪个文件。
-
让我们继续聊天中的讨论。
-
@Arrrr,如果您想在客户端进行文件检查,即使您也必须在服务器端进行检查,则只需检查文件的前四个字节:stackoverflow.com/questions/18299806/
-
我在聊天链接中解释了整个问题,请检查一下。
为我工作:
1 2 3 4 5 6 7 8 9 10 11 12 13
| var reader = new FileReader();
reader.onload = function (evt) {
var binary = '';
var bytes = new Uint8Array(reader.result);
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
console.log(btoa(binary))
}
reader.readAsArrayBuffer(file) |
如果使用FileReader读取文件,则整个文件将被加载到内存中。如果您想处理大文件,这只会导致Web浏览器立即崩溃。如果您真的有兴趣将文件作为Base64 String传递,建议您添加文件大小限制,以防止任何潜在的问题。结论是,FileReader类的任何一种方法都不适合该目的,除非您要处理的文件不大于100MG左右,否则将再次出现问题。
玩完之后,这里是解决方案:
1 2 3 4 5 6 7 8 9 10
| $("#file").change(function () {
var reader = new FileReader();
reader.readAsBinaryString(this.files[0]);
var fileName = this.files[0].name;
var fileType = this.files[0].type;
alert(fileType)
reader.onloadend = function () {
var base64Image = btoa(this.result);
}
} |
-
"此功能是非标准的,不在标准轨道上。请不要在面向Web的生产站点上使用它" developer.mozilla.org/en-US/docs/Web/API/FileReader/