предисловие
Мы, фронтенд-инженеры, неизбежно имеем дело с изображениями каждый день. Разработчики внешнего интерфейса, работающие над основными платформами электронной коммерции, могут чувствовать себя более очевидными.
Ниже приведены ямы, на которые я наступал раньше, когда имел дело с изображениями, и я поделюсь своим опытом с вами.
1. Репродукция сценария
При использовании Postman для запроса интерфейса возвращается это изображение (двоичное)
При просмотре сети в хроме тоже возвращается это изображение (бинарное).
Однако при печати отладки возвращаются искаженные символы.
Очевидно, тип данных был изменен. Если подумать, единственное место, где можно изменить тип данных, — это axios.
Я пошел посмотреть документацию axios, которая описана так
// `responseType` indicates the type of data that the server will respond with
// options are 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
responseType: 'json', // default
Таким образом, искаженные символы появляются, потому что:Axios по умолчанию возвращает текстовую форму json, а данные двоичного изображения преобразуются в текстовую форму json.
Как только причина найдена, решение легко.В axios типом возвращаемых данных по умолчанию для responseType является json, измените его на возвращаемый тип данных blob.
export function miniprogramQrcode (params) {
return axios.post(
env.MI_URL + '/XXXX/XXX/XXXX',
params,
// 将responseType的默认json改为blob
{
responseType: 'blob',
emulateJSON: true
}).then(res => {
if (res.data) {
return Promise.resolve(res.data)
} else {
throw res
}
}).catch(err => {
return Promise.reject(err)
})
}
Следующий вопрос: как работать с объектом blob и отображать его на странице интерфейса?
код показывает, как показано ниже:
createMiniQrcode (blob) {
let img = document.createElement('img')
img.onload = function (e) {
// 元素的onload 事件触发后将销毁URL对象, 释放内存。
window.URL.revokeObjectURL(img.src)
}
// 浏览器允许使用URL.createObjectURL()方法,针对 Blob 对象生成一个临时 URL。
// 这个 URL 以blob://开头,表明对应一个 Blob 对象。
img.src = window.URL.createObjectURL(blob)
document.querySelector('.imgQrCode').appendChild(img)
}
Вы думали, что это закончилось? Нет, нет, нет. Знать, как решить проблему, недостаточно.Думайте дивергентно через внешность.
2. Дивергентное мышление
Вообще говоря, есть два способа хранения изображений в бэкенде:
其一:可以将图片以独立文件的形式存储在服务器的指定文件夹中,再将路径存入数据库字段中;
其二:将图片转换成二进制流,直接存储到数据库的 Image 类型字段中.
Для первого метода хранения мы можем легко отобразить его, напрямую назначив путь хранения атрибуту src во внешнем интерфейсе.
Для второго метода хранения наш внешний интерфейс должен передать свой двоичный поток объекту BLOB-объекта, а затем сгенерировать временный URL-адрес через API BLOB-объектов и назначить его атрибуту src для отображения.
Оба метода хранения имеют соответствующие решения, которые, кажется, идеально решили проблему отображения изображения. Однако наши бизнес-сценарии разнообразны и изменчивы. Иногда мы также сталкиваемся с такими сценариями, например, после перетаскивания и загрузки изображения вам автоматически возвращается объект Blob, но, к сожалению, вы обнаруживаете, что использовали интерфейс стороннего сервиса только для получения данных в формате base64. Хочешь плакать без слез?
Итак, можно ли преобразовать три представления изображений, url, base64 и blob, чтобы удовлетворить потребности? Ответ положительный. следующим образом:
1. ссылка на base64
URL для пакета метода Base64
// 原理: 利用canvas.toDataURL的API转化成base64
urlToBase64(url) {
return new Promise ((resolve,reject) => {
let image = new Image();
image.onload = function() {
let canvas = document.createElement('canvas');
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
// 将图片插入画布并开始绘制
canvas.getContext('2d').drawImage(image, 0, 0);
// result
let result = canvas.toDataURL('image/png')
resolve(result);
};
// CORS 策略,会存在跨域问题https://stackoverflow.com/questions/20424279/canvas-todataurl-securityerror
image.setAttribute("crossOrigin",'Anonymous');
image.src = url;
// 图片加载失败的错误处理
image.onerror = () => {
reject(new Error('图片流异常'));
};
}
Вы можете назвать это:
let imgUrL = `http://XXX.jpg`
this.getDataUri(imgUrL).then(res => {
// 转化后的base64图片地址
console.log('base64', res)
})
2. base64 в блоб
Метод инкапсуляции base64 в blob
// 原理:利用URL.createObjectURL为blob对象创建临时的URL
base64ToBlob ({b64data = '', contentType = '', sliceSize = 512} = {}) {
return new Promise((resolve, reject) => {
// 使用 atob() 方法将数据解码
let byteCharacters = atob(b64data);
let byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
let slice = byteCharacters.slice(offset, offset + sliceSize);
let byteNumbers = [];
for (let i = 0; i < slice.length; i++) {
byteNumbers.push(slice.charCodeAt(i));
}
// 8 位无符号整数值的类型化数组。内容将初始化为 0。
// 如果无法分配请求数目的字节,则将引发异常。
byteArrays.push(new Uint8Array(byteNumbers));
}
let result = new Blob(byteArrays, {
type: contentType
})
result = Object.assign(result,{
// jartto: 这里一定要处理一下 URL.createObjectURL
preview: URL.createObjectURL(result),
name: `图片示例.png`
});
resolve(result)
})
}
Вы можете назвать это так:
let base64 = base64.split(',')[1]
this.base64ToBlob({b64data: base64, contentType: 'image/png'}).then(res => {
// 转后后的blob对象
console.log('blob', res)
})
3. блоб в base64
Метод инкапсуляции блоба в base64
// 原理:利用fileReader的readAsDataURL,将blob转为base64
blobToBase64(blob) {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.onload = (e) => {
resolve(e.target.result);
};
// readAsDataURL
fileReader.readAsDataURL(blob);
fileReader.onerror = () => {
reject(new Error('文件流异常'));
};
});
}
Вы можете назвать это так:
this.blobToBase64(blob).then(res => {
// 转化后的base64
console.log('base64', res)
})
Больше ссылок на base64, base64 и blob демонстрации взаимного преобразования, следите за обновлениями здесь, заинтересованные могут ткнутьпортал
ps: вышеописанный метод предназначен дляИграйте с потоковой передачей изображенийоптимизация, спасибо оригинальному автору.
В-третьих, краткое изложение методов обработки изображений.
1. Как хранить изображения в бэкенде
Как мы упоминали ранее, есть два способа хранения изображений в бэкенде.Давайте рассмотрим: во-первых, изображения могут храниться как независимые файлы в указанной папке сервера, а затем путь может храниться в поле базы данных;второй : преобразовать изображение в бинарный поток и сохранить его непосредственно в поле Тип изображения базы данных;
Итак, какой из этих двух способов хранения лучше?
Насколько я понимаю, в интернет-среде важен большой объем трафика, скорость базы данных и производительность. Как правило, практика хранения изображений в базе данных меньше, а больше - хранить путь к изображению в базе данных.При отображении изображения вам нужно только подключить путь к диску и загрузить изображение. Потому что картина принадлежит большому полю. Картинка может быть от 1м до нескольких метров. Такие большие полевые данные увеличивают нагрузку на базу данных и замедляют ее работу. Важно в случае больших одновременных доступов. Это опыт. Посетив анализ настройки производительности базы данных, проведенный dba, можно получить ответ: то есть изображения не должны храниться в базе данных.
Поэтому, если back-end брат вашей компании часто хранит изображение в базе данных в бинарном виде, а потом возвращает его вам на стыковку, вы должны знать, как его дуить (funny face).
Подробнее о том, как изображения или файлы хранятся в базе данныхПожалуйста, нажмите здесь
2. Как отображаются фронтальные картинки
Для передней части: Существует три способа отображения изображений во внешнем интерфейсе: url, base64, blob.
Какой из трех методов отображения более элегантен?
URL: Вообще говоря, рекомендуется использовать URL для отображения изображений. Если поле, переданное из бэкэнда, является путем к изображению.
base64: Если картинка большая и цветовой уровень картинки насыщенный, этот способ не подходит, так как строка в кодировке Base64 очень большая, что значительно увеличит HTML-страницу и повлияет на скорость загрузки. Если изображение похоже на загрузку или строку таблицы, размер крайне мал, но занимает один HTTP-запрос и будет использоваться во многих местах. Он очень подходит для оптимизации технологии "base64: URL-изображение"! Подробная демонстрационная презентация Чжан Синьсюй,Пожалуйста, нажмите здесь.
blob: когда серверная часть возвращает определенный двоичный поток изображения, как я сказал в воспроизведении сцены в первой части, внешний интерфейс использует контейнер больших двоичных объектов для его получения. Изображение лучше отображать в блобе.
4. Чувства
Давать, записывать, подводить итоги. Я буду записывать и разбирать проблемы, возникающие в проекте по крупицам. Я считаю, что это разрозненные ветки и листья, которые с увеличением опыта проекта вырастут в высокое дерево.
Мнения в этой статье ограничены моим текущим техническим уровнем, и неизбежно будут ошибки Добро пожаловать, чтобы оставить сообщение в области комментариев для обмена и исправления.
По мере улучшения технического уровня статья будет время от времени дорабатываться и оптимизироваться~ Вы можете связаться со мной следующими способами.
обо мне
- Моя домашняя страница github (нажмите, чтобы войти)
- Моя домашняя страница Nuggets (нажмите, чтобы войти)
- Домашняя страница моей короткой книги (нажмите, чтобы войти)
Обзорная статья:
Использованная литература: