Ответ 1
Важно помнить, что File наследует от Blob, File на самом деле не имеет метода среза, он получает этот метод из Blob. Файл просто добавляет несколько атрибутов метаданных.
Лучший способ думать о Blob (или файле) - это как указатель на данные, а не фактические данные. Похоже на дескриптор файла на других языках.
Фактически вы не можете получить данные в блоке без использования считывателя, который читает асинхронно, чтобы избежать блокировки потока пользовательского интерфейса.
Метод blob slice() просто возвращает другой Blob, но опять же, это не данные, это просто указатель на диапазон данных в исходном блоке, вроде как ограниченный указатель на представление. Чтобы фактически получить байты из нарезанного Blob, вам все равно нужно использовать читателя. В случае нарезанного блоба ваш читатель ограничен.
Это действительно просто предназначено для удобства, так что вам не нужно переносить кучу относительных и абсолютных смещений в вашем коде, вы можете просто получить ограниченный вид данных и использовать читателя так, как если бы вы были чтение из байта 0.
В случае XMLHttpRequest (при условии, что браузер поддерживает более новый интерфейс), данные будут передаваться по потоку и ограничены границами blob. В принципе, он будет работать так же, как вы могли бы подумать, что это сработает, если вы отправили указатель файла на метод потока (что в основном происходит под обложками). https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data#Sending_binary_data
По существу, это ленивый читатель. Если blob уже загружен/прочитан из файловой системы или был создан в памяти, он просто будет использовать это. Однако, когда вы используете файл, он будет лениво загружаться и транслироваться асинхронно из основного потока.
Основная логика заключается в том, что разработчики браузера никогда не хотят, чтобы чтение происходило синхронно, потому что оно могло блокировать основной поток, поэтому весь API был разработан вокруг этой основной философии. Обратите внимание, что Blob.slice() является синхронным - что вы знаете, что он фактически не выполняет IO, он просто настраивает границы и (возможно) указатели файлов.