Напишите это вверху
Небольшой первый запрос
Два дня назад в проекте было небольшое требование: фронтенд загружает файл бинарного потока, возвращаемый младшим братом в фоновом режиме.
Когда я впервые получил это требование, я почувствовал, что это очень просто (хотя я не могу, но я могу Baidu,)
Затем напишите следующий код:
let blob = new Blob([res.data]);
let fileName = `Cosen.csv`;
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveBlob(blob, fileName);
} else {
let link = document.createElement("a");
let evt = document.createEvent("HTMLEvents");
evt.initEvent("click", false, false);
link.href = URL.createObjectURL(blob);
link.download = fileName;
link.style.display = "none";
document.body.appendChild(link);
link.click();
window.URL.revokeObjectURL(link.href);
}
Этот кусок кода, я, вероятно,силаобъяснять:
Судите первымwindow.navigator.msSaveOrOpenBlob
для совместимостиIE
(кто хочет быть совместимым с этим ххIE
! ! )
тогда неIE
прохождениеURL.createObjectURL()
будетBlob
(Blob
Что это? понятия не имею? Неважно, я буду конкретен нижеделать видобъясняется) строится какobject URL
объект, указать имя файла и тип файла, создатьa
Ссылка имитирует щелчок для осуществления загрузки и, наконец, проходитURL.revokeObjectURL
Освободите созданный объект.
Хоть функция и реализована, но я в ней не разбираюсь~
затем следует не очень простое требование
Через несколько дней продукт выдал мне еще одно требование: обрезка изображения, загрузка и предварительный просмотр.
Хотя подобные потребности и слышал, но от руки толком не писал, а потом начал лазить по интернету (поиски всякие,). Но на этот раз все не так просто, как я думал.
В Интернете вы видите такие вещи, какFileReader
,canvas
,ArrayBuffer
,FormData
,Blob
эти существительные. Я совершенно ошеломлен, я только слышал о них обычно, и я не использую их много. После некоторого изучения я обнаружил, что все они относятся к категории знаний внешнего двоичного кода, поэтому, прежде чем начать бизнес, я собираюсь разобраться с задействованным внешним двоичным файлом.Как говорится: базовая основа определяет надстройку. 🙈
FileReader
HTML5
ОпределенныйFileReader
как файлAPI
Важные члены используются для чтения файлов, согласноW3C
Определение,FileReader
Интерфейс предоставляет методы для чтения файлов и модель событий, содержащую результаты чтения.
Создать экземпляр
var reader = new FileReader();
метод
имя метода | описывать |
---|---|
abort |
Прервать операцию чтения |
readAsArrayBuffer |
Асинхронно считывает содержимое файла побайтно, и результатArrayBuffer представление объекта |
readAsBinaryString |
Асинхронно считывает содержимое файла побайтно, результатом является двоичная строка файла |
readAsDataURL |
Прочитайте содержимое файла асинхронно и используйте результатdata:url строковое представление |
readAsText |
Асинхронно считывает содержимое файла по символам, а результат представляется в виде строки |
событие
название события | описывать |
---|---|
onabort |
Триггер по прерыванию |
onerror |
Срабатывает при ошибке |
onload |
Запускается после успешного завершения чтения файла |
onloadend |
Запускается при завершении чтения (независимо от успеха или неудачи) |
onloadstart |
Запускается, когда начинается чтение |
onprogress |
Загрузка |
Пример
Попробуем прочитать содержимое файла в виде строки:
<input type="file" id='upload' />
document.getElementById('upload').addEventListener('change', function (e) {
var file = this.files[0];
const reader = new FileReader();
reader.onload = function () {
const result = reader.result;
console.log(result);
}
reader.readAsText(file);
}, false);
ArrayBuffer
/TypedArray
/DataView 对象
ArrayBuffer
Давайте взглянемArrayBuffer
функция:
Давайте сначала представимArrayBuffer
,Потому чтоFileReader
имеетreadAsArrayBuffer()
метод, если файл для чтения представляет собой двоичные данные, наиболее целесообразно использовать этот метод для чтения, считанные данные представляют собойArraybuffer
объекта, посмотрите на определение:
ArrayBuffer
Объект, используемый для представления универсального буфера фиксированной длины необработанных двоичных данных.ArrayBuffer
нельзя манипулировать напрямую, но передать объект массива типа илиDataView
Объекты для работы, они будут представлять данные в буфере в определенном формате и через эти форматы читать и записывать содержимое буфера.
ArrayBuffer
Это также конструктор, который выделяет непрерывную область памяти, в которой могут храниться данные.
const buffer = new ArrayBuffer(8);
// ArrayBuffer 对象有实例属性 byteLength ,表示当前实例占用的内存字节长度(单位字节)
console.log(buffer.byteLength);
из-за невозможностиArraybuffer
Прямая работа, поэтому для работы нам нужно использовать другие объекты.TypedArray
(тип объект массива) иDataView
объект.
DataView 对象
Приведенный выше код создает 8-байтовую область памяти, и значение каждого байта по умолчанию равно 0.
Чтобы читать и записывать этот контент, вам нужно указать для него представление.DataView
Просмотреть создание, необходимо предоставитьArrayBuffer
Экземпляр объекта в качестве параметра.
DataView
Представление — этоArrayBuffer
Низкоуровневый интерфейс для чтения и записи нескольких числовых типов в объекте.
-
setint8()
отDataView
исходное положение сbyte
указанное смещение для счетчика (byteOffset
) хранить8-bit
число (один байт) -
getint8()
отDataView
исходное положение сbyte
указанное смещение для счетчика (byteOffset
) чтобы получить8-bit
число (один байт)
перечислить
new DataView(buffer, [, byteOffset [, byteLength]])
Пример
let buffer = new ArrayBuffer(2);
console.log(buffer.byteLength); // 2
let dataView = new DataView(buffer);
dataView.setInt(0, 1);
dataView.setInt(1, 2);
console.log(dataView.getInt8(0)); // 1
console.log(dataView.getInt8(1)); // 2
console.log(dataView.getInt16(0)); // 258
TypedArray
ДругаяTypedArray
вид, сDataView
Одно отличие представления состоит в том, что это не конструктор, а набор конструкторов, представляющих разные форматы данных.
TypedArray
объект описывает базовый буфер двоичных данных (binary data buffer
) массивообразного представления (view
).
Но он не может быть создан или даже доступен сам по себе, вы можете понимать его как интерфейс, у него много реализаций.
Выполнение
тип | диапазон значений отдельных элементов | размер (байты) | описывать |
---|---|---|---|
Int8Array | -128 to 127 | 1 | 8-битное двоичное целое число со знаком |
Uint8Array | 0 to 255 | 1 | 8-битное целое число без знака |
Int16Array | -32768 to 32767 | 2 | 16-битное двоичное целое со знаком |
Uint16Array | 0 to 65535 | 2 | 16-битное целое число без знака |
Пример
const buffer = new ArrayBuffer(8);
console.log(buffer.byteLength); // 8
const int8Array = new Int8Array(buffer);
console.log(int8Array.length); // 8
const int16Array = new Int16Array(buffer);
console.log(int16Array.length); // 4
Blob
Blob
используется для поддержки файловых операций. Проще говоря: вJS
, есть два конструктораFile
иBlob
, иFile
унаследовал всеBlob
характеристики.
Итак, на наш взгляд,File
Объект можно рассматривать как особыйBlob
объект.
сказал выше,File
объект – это спец.Blob
объект, то он может, естественно, вызывать напрямуюBlob
методы объекта. Давайте взглянемBlob
Какие методы существуют, и какие функции могут быть достигнуты с их помощью:Да, мы больше склоняемся к применению в реальных боях~
оBlob
Для более подробного ознакомления см.Blob
atob
иbtoa
base64
Я полагаю, что все будут знакомы с ним (если вы не знаете, см.здесь), наиболее часто используемой операцией может быть преобразование изображенияbase64
правильно?
перед строкой, за которой следуетbase64
Нам может понадобиться скопировать чей-то метод онлайн, и в большинстве случаев у вас нет времени, чтобы проверить, действительно ли этот метод надежен или нет.bug
.
отIE10+
Браузеры запускаются, все браузеры предоставляют его изначальноBase64
Метод кодирования и декодирования.
Декодирование Base64
var decodedData = window.atob(encodedData);
Кодировка Base64
var encodedData = window.btoa(stringToEncode);
Canvas
серединаImageData
объект
оCanvas
, я не буду вводить здесь слишком много, вы можете обратиться к конкретнымхолст документация
Сегодня я в основном буду говорить оCanvas
серединаImageData
Предметы (также чтобы проложить путь к некоторым базовым знаниям об элементе, обрезанном на картинке ниже~)
ImageData
объект, хранящийся вcanvas
Фактические пиксельные данные объекта, которые содержат следующие свойства только для чтения:
-
width
: Ширина изображения в пикселях. -
height
: высота изображения в пикселях. -
data
:Uint8ClampedArray
одномерный массив типа, содержащийRGBA
Форматировать целочисленные данные в диапазоне от 0 до 255 включительно.
СоздаватьImageData
объект
использоватьcreateImageData()
метод создания нового, пустогоImageData
объект.
var myImageData = ctx.createImageData(width, height);
Приведенный выше код создает новый определенный размерImageData
объект. Все пиксели настроены на прозрачный черный цвет.
получить данные о пикселях сцены
Чтобы получитьImageData
объект, вы можете использоватьgetImageData()
метод:
var myImageData = ctx.getImageData(left, top, width, height);
Запись пиксельных данных в сцену
ты можешь использовать этоputImageData()
метод для записи пиксельных данных в сцену.
ctx.putImageData(myImageData, dx, dy);
toDataURL
будетcanvas
Преобразовать вdata URI
Формат
Есть следующие<canvas>
элемент:
<canvas id="canvas" width="5" height="5"></canvas>
Можно получить следующим образомdata-URL
var canvas = document.getElementById("canvas");
var dataURL = canvas.toDataURL();
console.log(dataURL);
// "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNby
// blAAAADElEQVQImWNgoBMAAABpAAFEI8ARAAAAAElFTkSuQmCC"
К этому моменту я уже заложил основу для базовых знаний о двоичном коде. Вернемся к «не столь простому» новому требованию продукта, упомянутому в начале статьи: обрезка изображения, загрузка и предварительный просмотр.
На самом деле, как图片裁剪上传
У такого сообщества уже есть очень зрелые решения, такие какvue-cropper. Здесь я решил написать простую обрезку изображения от руки, потому что она использует много бинарных знаний, упомянутых выше, которые могут хорошо сочетать теорию с практикой.
Без лишних слов откройте Giao! !
Развитие спроса Giao Giao!
Давайте посмотрим на окончательный эффект:
Опубликовать здеськодовый адрес
Кроме того, я использовал картинку, чтобы разобраться во взаимосвязи между упомянутыми выше интерфейсными бинарными модулями, что очень поможет при разработке следующих требований:
Все требование разделено на следующие четыре шага:
1. Получите файл и прочитайте файл.
2. Получите координаты отсечения.
3. Обрежьте изображение.
4. Прочитайте предварительный просмотр обрезанного изображения и загрузите его.
получить файл и прочитать файл
Во-первых, давайте взглянем на файл сбора данных, упомянутый в первом шаге выше. соответствующийinput
границаhandleChange
событие:
handleChange = (event) => {
let file = event.target.files[0];
let fileReader = new FileReader();
fileReader.onload = (event) => {
this.setState({
file,
dataURL: event.target.result,
});
this.imageRef.current.onload = () => this.drawImage();
};
fileReader.readAsDataURL(file);
};
HTML5
Поддержка отinput[type=file]
Информация о файле может быть получена непосредственно из элемента, а также может быть прочитано содержимое файла.
Здесь нужно использоватьFileReader
, этот класс специально используется для чтения локальных файлов. Обычный текст или двоичный файл можно читать, но локальные файлы должны быть прочитаны с разрешения пользователя, то есть пользователь долженinput[type=file]
Вы можете прочитать этот файл, только если выберете его в .
пройти черезFileReader
Мы можем конвертировать файлы изображений вDataURL
, то есть сdata:image/png;base64
вид началаURL
, который затем может быть помещен непосредственно вimage.src
, чтобы отображалось локальное изображение.
Получить координаты обрезки
В основном здесьmousedown
,mousemove
,mouseup
Используйте в сочетании с событиями.
mousedown
событие нажатия мыши. Здесь нам нужно записать координаты начала при нажатии мыши, т.е.startX
иstartY
, при установке бита флагаstartDrag
установить какtrue
, отмечая начало движения мыши.
handleMouseDown = (event) => {
this.setState({
startX: event.clientX,
startY: event.clientY,
startDrag: true,
});
};
mousemove
Событие перемещения мыши. судитьstartDrag
заtrue
(то есть мышь начинает двигаться), а затем записывают расстояние, соответствующее движению.
handleMouseMove = (event) => {
if (this.state.startDrag) {
this.drawImage(
event.clientX - this.state.startX + this.state.lastX,
event.clientY - this.state.startY + this.state.lastY
);
}
};
mouseup
Событие «Мышь вверх». Здесь, чтобы записать координаты конечной точки падения мыши,lastX
иlastY
.
handleMouseUp = (event) => {
this.setState({
lastX: event.clientX - this.state.startX + this.state.lastX,
lastY: event.clientY - this.state.startY + this.state.lastY,
startDrag: false,
});
};
Обрезать изображение
В это время нам нужно использоватьcanvas
в настоящее время,canvas
То же, что и на картинке, поэтому создайте новуюcanvas
определить его высоту и ширину.
вставь картинку вcanvas
нужно позвонитьdrawImage
:
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
конкретныйAPI
использовать ссылкуMDN
ВверхdrawImage
drawImage = (left = this.state.lastX, top = this.state.lastY) => {
let image = this.imageRef.current;
let canvas = this.canvasRef.current;
let ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
let imageWidth = image.width;
let imageHeight = image.height;
if (imageWidth > imageHeight) {
let scale = canvas.width / canvas.height;
imageWidth = canvas.width * this.state.times;
imageHeight = imageHeight * scale * this.state.times;
} else {
let scale = canvas.height / canvas.width;
imageHeight = canvas.height * this.state.times;
imageWidth = imageWidth * scale * this.state.times;
}
ctx.drawImage(
image,
(canvas.width - imageWidth) / 2 + left,
(canvas.height - imageHeight) / 2 + top,
imageWidth,
imageHeight
);
};
Среди них мы также добавилиscale
, эта переменная используется для реализации изображения放大
,缩小
эффект.
И он будет судить о соотношении размеров между шириной и высотой изображения, чтобы реализовать изображение вcanvas
соответствующую адаптацию.
Прочтите обрезанное изображение и загрузите его
Тогда мы получимcanvas
информация на картинке, используйтеtoDataURL
может быть преобразован в вышеуказанный используемыйDataURL
.
confirm = () => {
let canvas = this.canvasRef.current;
let ctx = canvas.getContext("2d");
const imageData = ctx.getImageData(100, 100, 100, 100);
let avatarCanvas = document.createElement("canvas");
avatarCanvas.width = 100;
avatarCanvas.height = 100;
let avatarCtx = avatarCanvas.getContext("2d");
avatarCtx.putImageData(imageData, 0, 0);
let avatarDataUrl = avatarCanvas.toDataURL();
this.setState({ avatarDataUrl });
this.avatarRef.current.src = avatarDataUrl;
};
затем выньте этоbase64
информация, повторное использованиеwindow.atob
Преобразование в двоичную строку. ноwindow.atob
Преобразованный результат по-прежнему является строкой, прямо дающейBlob
все равно пойдет не так. Так что используйте сноваUint8Array
Преобразуйте это.
Затем обрезанный файл сохраняется вblob
, мы можем рассматривать его как обычный файл и добавить вFormData
и загрузить его на сервер.
upload = (event) => {
// console.log("文件url", this.state.avatarDataUrl);
let bytes = atob(this.state.avatarDataUrl.split(",")[1]);
console.log("bytes", bytes);
let arrayBuffer = new ArrayBuffer(bytes.length);
let uInt8Array = new Uint8Array();
for (let i = 0; i < bytes.length; i++) {
uInt8Array[i] = bytes.charCodeAt[i];
}
let blob = new Blob([arrayBuffer], { type: "image/png" });
let xhr = new XMLHttpRequest();
let formData = new FormData();
formData.append("avatar", blob);
xhr.open("POST", "/upload", true);
xhr.send(formData);
};
Ссылаться на
https://es6.ruanyifeng.com/#docs/arraybuffer
https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas
❤️ Люблю тройное комбо
1. Если вы считаете, что эта статья неплохая, заходите сюдаПоделиться, Нравится, ИзбранноеСанлиан, пусть больше людей увидят это~
2. Подпишитесь на официальный аккаунтпередний лес, регулярно снабжаем вас свежими и галантереями и хорошими товарами.
3. На спецучастках носите маску и пользуйтесь средствами индивидуальной защиты.