Вставка картинки из буфера обмена в форматированный документ

1. 129 22.01.20 19:07 Сейчас в теме
Выявлен нюанс при работе с форматированным документом - при вставке скриншота, через буфер обмена, картинку не возможно отправить в почтовое сообщение.

Релиз платформы: 8.3.15.1830

Режим совместимости: 8.3.14

Все работало нормально, т.к. все использовали одну программу для сриншотов getgreenshot

Но в какой-то момент скриншоты, вставляемые в форматированный документ, перестали приходить в почтовых сообщениях. Часть приходит нормально, часть пустые картинки.

Анализ показал, что часть картинок вставляется как "<img src="e1cib/....>", часть как "<img src="data:image/png;base64,....>" и с ним проблем нет.
"<img src="data:image/png;base64,....>", в момент отправки спокойно преобразуются в картинку через Base64Значение().

Но появились картинки "<img src="data:image/bmp;base64,....>" и они не преобразуются в картинку через Base64Значение().

Пока вставили функцию для проверки, которая проверяет есть ли такие картинки в форматированном документе:

Функция ЕстьИзображенияНеПоФормату(ФорматированныйДокументВход) Экспорт

Для Каждого ЭлементФД Из ФорматированныйДокументВход.Элементы Цикл

Если ТипЗнч(ЭлементФД) = Тип("ПараграфФорматированногоДокумента") Тогда

Если ЕстьИзображенияНеПоФормату(ЭлементФД) Тогда
Возврат Истина;
КонецЕсли;

ИначеЕсли ТипЗнч(ЭлементФД) = Тип("КартинкаФорматированногоДокумента") Тогда

Если ТипЗнч(ЭлементФД.Картинка) = Тип("Строка") Тогда

ДанныеСтрока = WS_Base64.ПолучитьДанныеКартинкиИзСтрокиBase64(ЭлементФД.Картинка);
СтруктураКартинка = WS_Base64.ПолучитьКартинку(ДанныеСтрока);

Если СтруктураКартинка.Свойство("Картинка") Тогда

Если СтруктураКартинка.Картинка.Формат() = Неопределено Тогда
Возврат Истина;
КонецЕсли;

Иначе

Возврат Истина;

КонецЕсли;

КонецЕсли;

КонецЕсли;

КонецЦикла;

КонецФункции
Показать

Вспомогательные функции:

Функция ПолучитьКартинку(СтруктураВход,ЗаписатьФайл=Ложь)  Экспорт 
    
    Если ТипЗнч(СтруктураВход) <> Тип("Структура") Тогда
         Возврат СтруктураВход;
     КонецЕсли; 
    
    Если СтруктураВход.Свойство("РасширениеФайла") Тогда 
        Возврат СтруктураВход;
    КонецЕсли;
    
    Если СтруктураВход.Свойство("СтрокаBase64") Тогда 
        Возврат СтруктураВход;
    КонецЕсли;
    
    Если ЗаписатьФайл Тогда
        
        ИмяВременногоФайла     = ПолучитьИмяВременногоФайла(СтруктураВход.РасширениеФайла);
        Base64Значение(СтруктураВход.СтрокаBase64).Записать(ИмяВременногоФайла);
        СтруктураВход.Вставить("ИмяФайла",ИмяВременногоФайла);
        СтруктураВход.Вставить("Картинка", Новый Картинка(ИмяВременногоФайла));
        
    Иначе 
        
        СтруктураВход.Вставить("Картинка", Новый Картинка(Base64Значение(СтруктураВход.СтрокаBase64)));
        
    КонецЕсли; 

    Возврат СтруктураВход; 

КонецФункции

Функция ПолучитьДанныеКартинкиИзСтрокиBase64(Знач СтрокаВход) Экспорт 
    
    СтруктураВозврат = Новый Структура;
    СтруктураВозврат.Вставить("СтрокаBase64","");
    СтруктураВозврат.Вставить("РасширениеФайла","");
     
    Если ТипЗнч(СтрокаВход) = Тип("Строка") Тогда
        
        ПозПоиска = СтрНайти(СтрокаВход,";base64,");
        
        Если ПозПоиска>0 Тогда
            
            РасширениеФайла    = Лев(СтрокаВход,ПозПоиска-1);
            РасширениеФайла = СтрЗаменить(НРег(РасширениеФайла),"data:image/","");
            СтрокаBase64    = Сред(СтрокаВход,ПозПоиска+СтрДлина(";base64,"));
            СтрокаBase64    = СтрЗаменить(СтрокаBase64, Символы.ВК, "");
            СтрокаBase64    = СтрЗаменить(СтрокаBase64, Символы.ПС, "");
            
            СтруктураВозврат.СтрокаBase64 = СтрокаBase64;
            СтруктураВозврат.РасширениеФайла = РасширениеФайла;
            
            
        КонецЕсли;
        
    КонецЕсли;
    
    Возврат СтруктураВозврат; 
        
КонецФункции


 
Показать





Пользователь в этом случае либо меняет программу для принтскрина, либо вставляет через файл.


Но остался вопрос - почему "<img src="data:image/png;base64,....>" не преобразуется в картинку. Кто-нибудь сталкивался с подобным?
Ситуация выявлена при использовании программы https://screenshoter.mail.ru/
Ответы
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
2. user774630 22.01.20 22:22 Сейчас в теме
Александр, тут вам едва ли помогут. Это вопрос для партнерской конференции, да и там, скорее всего, отфутболят на линию поддержки.
Я в свое время с ними общался по подобному вопросу. Например, картинка из письма MS Outlook, вставленная в буфер обмена, вставлялась в ФормДок как ссылка на папку Темп и не сохранялась в БД, а картинка через Ножницы (приложение Windows) вставялась нормально - через Base64. Могу путать детали, было давно.
Суть в том, что даже на партнерке я не получил ни ответа, ни помощи.
3. Adrenal1n 3 30.01.21 20:13 Сейчас в теме
На самом деле вопрос очень интересный и для меня актуальный. Дело в том, что при вставке скрина он вставляется как строка <img src="data:image/bmp;base64,....>. Но на самом деле это не base64 текст, там много запрещенных для этого формата символов и я никак не могу понять как именно форматированный документ ее декодирует. Проблема в том, что если вставить пару картинок из буфера в таком формате, то форма с форматированным документом начинает жутко тормозить, открывается по 10 минут, без преуменьшения. Оно и понятно - эта строка в длину несколько десятков тысяч символов. Как ее декодировать?
4. Adrenal1n 3 30.01.21 22:08 Сейчас в теме
Разобрался. Нужно в строке <img src="data:image/bmp;base64,....> заменить все подчеркивания и минусы на символы, которые используются в base64 формате, дополнить строку символами "=" до строки длины, которая делится на 4, а потом использовать декодировку Base64Значение().
Вот простенькая функция, которая делает из строки, которая приходит из любого скриншотера двоичные данные, из которых можно сделать картинку просто конструктором Новый Картинка:

Функция КонвертироватьВДвоичныеДанные(Строка) 
	СтрокаВозврата = СтрЗаменить(Строка, "data:image/jpeg;base64,", "");
	СтрокаВозврата = СтрЗаменить(СтрокаВозврата, "data:image/bmp;base64,", "");
	СтрокаВозврата = СтрЗаменить(СтрокаВозврата, "data:image/jpg;base64,", "");
	СтрокаВозврата = СтрЗаменить(СтрокаВозврата, "data:image/png;base64,", "");
	СтрокаВозврата = СтрЗаменить(СтрокаВозврата, "_", "/");
	СтрокаВозврата = СтрЗаменить(СтрокаВозврата, "-", "+");
	СтрокаВозврата = СтрЗаменить(СтрокаВозврата, Символы.ВК, "");
	СтрокаВозврата = СтрЗаменить(СтрокаВозврата, Символы.ПС, "");
	
	СтрокаДополнения = "";
	КоличествоРавно = 4 - СтрДлина(СтрокаВозврата)%4;
	Если КоличествоРавно <> 4 Тогда
		Для Счетчик = 1 По КоличествоРавно Цикл
			СтрокаДополнения = СтрокаДополнения + "=";
		КонецЦикла;
	КонецЕсли;
	Возврат  Base64Значение(СтрокаВозврата + СтрокаДополнения);
КонецФункции
Показать


благо операции со строками в 1с происходят достаточно быстро, тестил на строках длиной больше 4 миллионов (это полноразмерный скрин двух мониторов).
5. qSergey 124 03.05.21 11:23 Сейчас в теме
(4)
Функция КонвертироватьВДвоичныеДанные(Строка)
СтрокаВозврата = СтрЗаменить(Строка, "data:image/jpeg;base64,", "");
СтрокаВозврата = СтрЗаменить(СтрокаВозврата, "data:image/bmp;base64,", "");
СтрокаВозврата = СтрЗаменить(СтрокаВозврата, "data:image/jpg;base64,", "");
СтрокаВозврата = СтрЗаменить(СтрокаВозврата, "data:image/png;base64,", "");
СтрокаВозврата = СтрЗаменить(СтрокаВозврата, "_", "/");
СтрокаВозврата = СтрЗаменить(СтрокаВозврата, "-", "+");
СтрокаВозврата = СтрЗаменить(СтрокаВозврата, Символы.ВК, "");
СтрокаВозврата = СтрЗаменить(СтрокаВозврата, Символы.ПС, "");

СтрокаДополнения = "";
КоличествоРавно = 4 - СтрДлина(СтрокаВозврата)%4;
Если КоличествоРавно <> 4 Тогда
Для Счетчик = 1 По КоличествоРавно Цикл
СтрокаДополнения = СтрокаДополнения + "=";
КонецЦикла;
КонецЕсли;
Возврат Base64Значение(СтрокаВозврата + СтрокаДополнения);
КонецФункции
Показать

Спасибо за твой труд!
Оставьте свое сообщение
Вопросы с вознаграждением