JavaScript: Read big files in chunks — WebkitBlobResource error 1 on iOS Safari
I’m trying to read a rather big file in chunks using FileReader (File selected from a field). Works fine on Android, Chrome, Firefox etc., but somehow on iOS Safari the FileReader stops reading the chunks exactly after 60 seconds. The error I am seeing is WebkitBlobResource error 1. Makes me wonder if this is some kind of permission error or somehow iOS Safari revokes the File blob.
For easier and direct debugging on an iOS device using Safari I'm gonna link this JSFiddle:
Just select a file and wait for the counter do go to zero.
All of this makes it impossible for some users to upload large files. Our webapp processes each chunk individually (encryption), so we have to work with chunks.
Ошибка при загрузке Blob в img в Safari (ошибка WebKitBlobResource 1.)
Я пытаюсь сохранить большой двоичный объект в localforage, а затем получить его и отобразить. Некоторое время он работает нормально, но после нескольких обновлений страницы или закрытия браузера я получаю сообщение об ошибке на некоторых блобах. Полная ошибка выглядит следующим образом:
Вот остальная часть моего кода. Сохранить элемент в localforage:
Загрузить элемент из localforage:
Добавьте большой двоичный объект в источник изображения:
Кажется, это проблема, специфичная для Safari, так как я не могу воспроизвести ее в Chrome.
1 ответ
Обновить TLDR;
Большие двоичные объекты в indexeddb ненадежны в iOS Webkit. Поэтому вместо этого сохраните свои большие двоичные объекты как буфер массива, а тип большого двоичного объекта — как строку в indexeddb. Вы можете получить ArrayBuffer и тип большого двоичного объекта, например:
Если вы хотите получить данные из indexeddb и отобразить их, просто создайте новый большой двоичный объект из ArrayBuffer и введите:
Изучение
У меня очень похожая проблема с iOS WebKit/safari: я также сохраняю изображения и видеоблобы, полученные с сервера, в файле indexeddb. Затем большие двоичные объекты извлекаются и преобразуются в URL-адрес с помощью createObjectUrl(). Это прекрасно работает во всех браузерных движках, кроме WebKit/safari. iOS WebKit/safari работает только первые пару раз. Я не нашел идеального решения, но пока могу поделиться своими выводами:
Как правило, все комментарии к подобным проблемам говорят о том, что «блобы в WebKit ненадежны».
Есть несколько возможных обходных путей: https://stackoverflow.com/a/60075517/13517617 Мне все еще нужно попробовать этот хотя.
Также мы можем использовать fileReader для создания строки base64 и использовать ее как src. вместо createObjectUrl(). Этого можно добиться следующим образом:
Это не идеальное решение, так как теперь у нас есть несколько обратных вызовов.
Есть некоторые подсказки, указывающие на то, что MIME-тип BLOB-объектов должен быть указан правильно, чтобы он постоянно работал в iOS WebKit/safari.
Я копну глубже и поделюсь своим окончательным ответом здесь. Может быть, кто-то еще быстрее или сталкивался с этой проблемой раньше.
Failed to load resource: The operation couldn’t be completed. (WebKitBlobResource error 1.) #536
In Safari, there is now a new error, where there wasn’t in previous versions.
Failed to load resource: The operation couldn’t be completed. (WebKitBlobResource error 1.)
The PDF then never renders in Safari.
This doesn’t happen in Chrome.
To Reproduce
Make and render a PDF in browser, using Safari.
Desktop (please complete the following information):
- OS: [e.g. MacOS]
- Browser [e.g safari]
- React-pdf version [e.g. v1.4.1]
The text was updated successfully, but these errors were encountered:
It was desktop, yeah, all up to date. Latest react, etc, etc.
I’ll try to find some time in the next couple days to look into it further.
This appears to be caused by the use of <PDFViewer> . When I try to playground, it doesn’t happen and when I comment out the viewer, I can render it a bunch of times in a row successfully.
It happens on both localhost and a custom domain.
So, in Safari, it will sometimes render the PDF but then if you close the PDF and try again, it will often block — with the viewer opening, but a blank white PDF. Then, often closing the browser window and trying to render again will be successful. Other times you need to do that a few times. It’s quite inconsistent.
I’d say the error rate is about 30-40 percent of the times trying to render the, so it’s pretty frequent.
Please let me know if there is anything I can get you to help troubleshoot and move this issue along. It effectively means Safari users cannot generate PDFs.
I’ve found this thread randomly, because I’m looking into the same Safari issue.
You might be interested in this:
Apparently it’s a bug with Safari.
This issue happening on Safari is likely due to jamming the main event loop with either too long ticks i.e execution stacks. Or too many timeouts scheduled in a short time i.e too frequently.
That is what I was able to conclude, while I was seeing this error with a completely different type of application than this PDF lib here.
It seems that some microtasks then just get dropped of the queue, which causes some of the async blob-data-extraction resolutions to just fail like this 🙂 It seems to be somewhat cut off in the depths of the runtime, as at the JS layer I would see this error in the console, but there wasnt any place where I could actually catch this promise rejection anywhere that it would claim 🙂 Sort of buggy behavior indeed, at least as the catch-handlers I set on those Blob#arrayBuffer methods never get called (in my case I dont convert the data to a file for download, but I get data as messages from an RTC channel, which uses blobs internally).
EDIT: Was almost omitting to clearly give the helpful info to fix/workaround (but pretty much gave it above): When you try to access the blob data in any way, you need to make sure you reduce the «pressure» on the main thread in any way. That means, defer/slice all tasks in any way possible that might «block» it. Or even use a worker. Unfortunately the issue here is that this error seems not catchable that well, so it is not possible to implement retry (wasnt in my case at least).
Error loading Blob to img in Safari (WebKitBlobResource error 1.)
I am trying to save a blob to localforage and then retrieve it and display it. It works fine for a while, but after a couple of page refreshes or browser closes I get an error on some of the blobs. The complete error is as follows:
Here is the rest of my code. Save item to localforage:
Load item from localforage:
Add blob to image source:
This seems to be a Safari specific problem, as I am not able to replicate it in Chrome.
1 Answer 1
Update TLDR;
Blobs in indexeddb are unreliable in iOS Webkit. So instead save your blobs as array buffer and the type of the blob as a string in the indexeddb. You can get the ArrayBuffer and the type of a blob-like this:
When you want to retrieve the data from the indexeddb and display it just create a new blob from the ArrayBuffer and type:
Investigation
I have a very similar issue on iOS WebKit / safari: I also store images and video blobs received from the server in the indexeddb. The blobs are then retrieved and converted to an URL with createObjectUrl(). This works perfectly on all browser engines except WebKit / safari. iOS WebKit / safari only works the first couple of times. I have not found a perfect solution but I can share my findings so far:
Generally, all comments to similar issues are saying "blobs on WebKit are unreliable".
There are some possible workarounds: https://stackoverflow.com/a/60075517/13517617 I still have to try this one though.
Also what we may can do is use the fileReader to create a base64 String and use this as src. instead of createObjectUrl(). This can be achieved like this:
This is not an ideal solution as we now have some callbacks.
There are some hints pointing to that the mime type of the blobs have to be specified correctly to make it work in iOS WebKit / safari all the time.
I will dig deeper and share my final answer here. Maybe some else is faster or has encountered this issue before.