Как прочитать двоичное содержимое файла в строку (аналог file_get_contents() в php)?
Необходимо передавать такое содержимое файла в http-запросе, но без кодирования в base64.
(7) PetroP,
я в http сервисах делал такую конструкцию, чтобы вернуть страничку, с картинками..
т.к. http сервис не может вернуть картинки файлами, мне пришлось их кодировать в текст,
и в http страницу вместо имени файла СтрЗаменой впендюривать этот текст,
в итоге все работает.
(17) Boneman, у них погоду кривой алгоритм и не умеет или не правильно читает такую строку!
Поэтому они и привели в пример скрипт, которые они научились использовать для чтения файлов.
(3) PetroP,
А тебе что надо? Функция из PHP file_get_contents эта функция безопасна для обработки данных в двоичной форме, то есть не изменяет исходные данные вставками конца строк и прочее.
Прочитать (Read)
Синтаксис:
Прочитать(<РазмерСтроки>)
Параметры:
<РазмерСтроки> (необязательный)
Тип: Число.
Размер возвращаемой строки. Если параметр не указан, текстовый файл читается до конца.
Возвращаемое значение:
Тип: Строка; Неопределено.
В случае, если читаемый файл завершен, то возвращается Неопределено.
Описание:
Строка нулевой длины не является признаком конца файла.
Пример:
Текст = Новый ЧтениеТекста("d:\win.txt", КодировкаТекста.ANSI);
Стр = Текст.Прочитать(10);
Пока Стр <> Неопределено Цикл // чтение файла по 10 символов
Сообщить(Стр);
Стр = Текст.Прочитать(10);
КонецЦикла;
(9) Boneman, ну вот читаю файл jpg. При прочтении в 1с и последующей записи/вставке/выводе от содержимого (которое я могу увидеть в том же notepade++) остается четыре символа ("яШяа"). Может я не правильно читаю?
ты бы код привел который читаешь,
ну и текстовые редакторы, совсем не факт что - смогут обработать такую строку, файл ведь может состоять из чисел, которые не являются символами, или будут служебными какими то значениями.
Как вот он отобразит "0" - да х.б.з.
Двоичные данные и есть двоичные данные.
(22) Xershi, Да...а там будут именно цифровые коды...бинарные данные. Есть функция сравнения файлов любых между собой и поиск как числовой так и строковой. То есть можно сравнить на соответствие входные данные и исходящие на предмет расхождения и в каком месте.
(21) avto-torg, это я к тому, что после прочтения в 1с и сохранения в другой файл (т. е. прочитали текст из одного файла и записали этот же текст в другой новый файл средствами 1с) только эти символы и остаются. Даже не надо открывать хекс-редактор чтобы понять, что результат не соответствует источнику.
(25) Boneman, возможно действительно дело в кодировке (хоть и перепробовал самые популярные).
Вот сейчас сделал с помощью последовательного чтения - размер совпадает, но контрольные суммы разные. Теперь можно и побайтно сравнить...
(26) PetroP, ну текст то оно читает сразу одним куском
ТекстФайла = ТекстовыйДокумент.ПолучитьТекст();
а все остальные замуты, для того, чтобы обмануть программу и заставить ее этот текст обратно в файл воспроизвести.
я так понимаю, для твоей задачи это и не нужно, строка у тебя есть - и передавай ее, куда надо
(31) spacecraft, да понятно. Не буду же я приводить все возможные вариации. С "ISO-8859-1" тоже сделал. Результат печальный.
Если вместо "ТекстовыйДокумент" использовать последовательный доступ к тексту, то файл назначения уже заполняется, но размеры файлов не совпадают.
45.
Messenger Unchained
29.03.16 16:59 Сейчас в теме
(34) Это что-то новое в веб-разработке, передавать файл через урл.
Ты точно этого хочешь? У того же iis насколько я помню, длина урла обрезается до 4 килобайт по избежание.
Я правильно понимаю твое желание, грубо говоря, прочитать файл с диска, "вставить его в адресную строку браузера" и нажать Пыщь?
(45) Messenger Unchained, ты посмотри (8) (аргумент "attachments") и ответь на свой вопрос. Я вполне допускаю, что разработчики что-то налажали в описании.
Прочитали файл как однобайтовую строку и прошлись по нему UrlEncode. И ниже "настоятельно рекомендуют использовать POST-запросы"
Ну и сделай тоже самое - передай POST запрос типом application/x-www-form-urlencoded и значением переменной - результатом вызова КодироватьСтроку. А прочитать ее надо как ЧтениеТекста.Прочитать() в кодировке ISO-8859-1. Ну и при кодировании указать тоже самое
(47) Messenger Unchained, кэп? Я, собственно, так и делаю, если проследить тему с начала.
Но все же интересно, скажи, как специалист, это "что-то новое в веб-разработке, передавать файл через урл"?
52.
Messenger Unchained
30.03.16 10:21 Сейчас в теме
(49) PetroP, у тебя там в начале какие-то чтение файла и текстовый документ. Передавать файл через урл - порочная практика, так как на пути может встретится прокси с ограничением размера урла. Параметры при передаче через пост могут передаваться как через урл так и через тело. При передаче через урл см. выше.
Извини, я ограничен временем и разжовывать тебе весь http протокол не буду. Однако замечу, что надо иметь представление о предметной области автоматизации. 1Снику - особенно.
(52) Messenger Unchained, ты не понимаешь одного: я не пишу стандарты и требования api web-сервиса. Поэтому, разглагольствования на тему "принято/непринято" здесь не уместны - это к создателям таких стандартов и требований.
Далее, если тебе не понятны "какие-то чтение файла и текстовый документ" и ты не можешь предложить иной способ получения строки двоичных данных средствами 1с, то о чем мы вообще разговариваем.
Извини, я ограничен временем и разжовывать тебе весь http протокол не буду. Однако замечу, что надо иметь представление о предметной области автоматизации. 1Снику - особенно.
Представление я имею. Я не имею углубленных знаний протокола http, и такие знания не являются необходимыми для "1Сника". Да и в данном случае они не нужны.
(1) PetroP, почитав стандарт Base64 легко можно понять, что там даже есть пояснение:
Применение в веб-приложениях[править | править вики-текст]
Кодирование Base64 может быть полезно, если в окружении HTTP используется информация, длину которой можно точно определить. Также многим приложениям необходимо кодировать двоичные данные для удобства включения в URL, скрытые поля форм, и здесь Base64 удобно не только для компактного представления, но и относительной нечитаемостью для попытки выяснения случайным человеком-наблюдателем природы данных.
Использование URL-кодировщика над стандартом Base64, несмотря на это, неудобно, так как он преобразует символы '/' и '+' в специальные шестнадцатеричные последовательности. Если позднее эта строка используется вместе с базой данных или через гетерогенные системы, они прекращают работу на символе '%', сгенерированном URL-кодировщиком (потому что символ '%' также используется в ANSI SQL как шаблон).
По причине этого существует изменённый Base64 для URL,где не используется заполнение символом '=' и символы '+' и '/' соответственно заменяются на '*' и '-', так что использование кодеров/декодеров URL перестаёт быть необходимым и не имеет никакого воздействия на длину закодированного значения, оставляя ту же самую закодированную форму, неповреждённую для использования в реляционных базах данных, веб-формах и идентификаторах объекта вообще. Стандартом Base64-кодирования URL адресов признается вариант, когда символы '+' и '/' заменяются, соответственно, на '-' и '_' (RFC 3548, раздел 4).
Другой вариант называется изменённый Base64 для регулярных выражений, использует '!-' вместо '*-', для того, чтобы заменить стандартный Base64 '+/', потому что оба '+' и '*' могут быть зарезервированы для регулярных выражений (отметим, что '[]', используемый выше в IRCu варианте, может не работать в этом контексте).
Имеются другие варианты, которые используют '_-' или '._', если строка Base64 должна быть использована вместе с идентификаторами для программ, или '.-' для использования в токенах имён XML (Nmtoken), или '_:' в более ограниченных идентификаторах XML (Name). В некоторых случаях для URL применяется Base58, который не использует символы '+/'.
(43) Xershi, не совсем понял мысль. Задачу сделал как говорил в (36) с помощью "ЧтениеФайла" и принудительным указанием символа перевода строки. "ТекстовыйДокумент" почему-то не работает (как на 8.3, так и на 8.2), что и ввело в заблуждение...
(44) PetroP, я про то что твои разрабы написали не использовать бейс64 чистый, потому что обмен идет по веб и стоит просто переписать станрдарт, т.е. выполнить подмену символов.
(48) Xershi, не хочу углубляться в эксперименты.
Там дальше в описании примеров на пхп есть два варианта для "гет" и "пост". Я не спец в пхп, но что-то мне кажется, что в варианте "пост" файл отправляется в теле запроса (в отличие от примера для "гет"). Кто-нибудь может это подтвердить или опровергнуть?
(50) В варианте "POST" содержимое файла отправляется в теле запроса. Вот примеры шестилетней давности, актуальные до сих пор.
Передача файлов и данных на веб-сервер средствами 1С:Предприятие 8.X методом POST
Вариант с передачей обычного файла. http://infostart.ru/public/20017/
(51) Поручик, я этот пример смотрел в первую очередь, как и говорил в (34).
Вот сейчас склоняюсь все-таки к тому, что описание методов делали люди, которые не должны были этого делать из-за отсутствия компетенции...
Будем пробовать...
(54) И запомни - файл не должен быть в url-строке, так как есть ограничения на передачу данных в GET-строке. Тебе правильно написали. В данном случае знания протокола http для понимания того, что ты хочешь сделать, нужны.
(55) Поручик, ограничения не описаны в стандартах, они носят сугубо практический характер (зависят от клиента / броузера и от сервера). Вот поэтому знания протокола никак не помогут в данном вопросе.
Суть кодирования сводится к тому чтобы двоичные данные представить в виде текста. Потом раскодировав их можно получить обратно двоичные данные и из них получить картинку или другой не текстовый файл.
Вобщем пока остановился на сборке файла назначения последовательным доступом к тексту с указанием символа перевода строки. Результат отличается только одним лишним символом перевода строки в конце файла.
Вытащил из CRM для метода SendMail достаточно следующего кода:
Тут реализована отправка письма UniSender и рабочий механизм с сложением файлов к письму.
Функция ОтправитьПисьмо(ТелоПисьма,api_key, Отправитель, EmailОтправителя, Кому, СписокРассылки="", ТекстОтвета) Экспорт
СтруктураОтвета=Новый Структура;
Уник =СТрока(новый УникальныйИдентификатор());
Ошибка="";
ИдРассылки = "";
Если ПустаяСтрока(Ошибка) Тогда
Ресурс = "/sendEmail?format=json";
//ТелоПисьма=ПараметрыПисьма.Тело;
attachments="";
НомерВложения = 0;
//Для Каждого СтрокаТаблицы Из ПараметрыПисьма.Вложения Цикл
// НомерВложения = НомерВложения + 1;
// ИмяВложения = СтрЗаменить(СтрокаТаблицы.Ключ, "_", "");
// ИмяВременногоФайла = КаталогВременныхФайлов()+ИмяВложения;
// Если ТипЗнч(СтрокаТаблицы.Значение) = Тип("ДвоичныеДанные") Тогда
// СтрокаТаблицы.Значение.Записать(ИмяВременногоФайла);
// ИначеЕсли ТипЗнч(СтрокаТаблицы.Значение) = Тип("Структура") Тогда
// СтрокаТаблицы.Значение.ДвоичныеДанные.Записать(ИмяВременногоФайла);
// КонецЕсли;
// Текст = Новый ТекстовыйДокумент();
// Текст.Прочитать(ИмяВременногоФайла, "ISO-8859-1", Символы.ПС);
// Стр = Текст.ПолучитьТекст();
// attachments=attachments+"&attachments["+ИмяВложения+"]="+КодироватьСтроку(Стр, СпособКодированияСтроки.КодировкаURL, "ISO-8859-1");
// Если ТипЗнч(СтрокаТаблицы.Значение) = Тип("Структура") И СтрНайти(ТелоПисьма, "src=""cid:"+СтрокаТаблицы.Значение.Идентификатор) > 0 Тогда
// ТелоПисьма = СтрЗаменить(ТелоПисьма, "src=""cid:"+СтрокаТаблицы.Значение.Идентификатор, "src="""+Строка(НомерВложения)+"_"+ИмяВложения);
// КонецЕсли;
//КонецЦикла;
ТелоПисьма=КодироватьСтроку(ТелоПисьма, СпособКодированияСтроки.КодировкаURL);
АдресЭлектроннойПочты = "&email=" + КодироватьСтроку(Кому, СпособКодированияСтроки.КодировкаURL);
//Для Каждого СтрокаТаблицы Из ПараметрыПисьма.Кому Цикл
// АдресЭлектроннойПочты=АдресЭлектроннойПочты+"&email[]="+ + СтрокаТаблицы.Адрес;
// // АдресЭлектроннойПочты="&email=" + СтрокаТаблицы.Адрес;
//КонецЦикла;
СтрокаЗапроса="&api_key="+api_key
+"&platform=1c_UT_Zapovednik"
+"&track_read=1"
//+"&ref_key[]="+УНИК
+"&track_links=1"
+"&attach_multi=0"
+АдресЭлектроннойПочты
+"&sender_name="+?(ЗначениеЗаполнено(Отправитель), Отправитель, EmailОтправителя)
+"&sender_email="+EmailОтправителя
+"&list_id="+СписокРассылки
+?(ПустаяСтрока(ИдРассылки),"","&user_campaign_id="+ИдРассылки)
+"&subject="+КодироватьСтроку("ТЕСТ", СпособКодированияСтроки.КодировкаURL)
+"&body="+ТелоПисьма
+attachments
;
СтруктураОтвета=ПолучитьЗначениеИзОтветаJSON(ВыполнитьЗапрос(СтрокаЗапроса,Ресурс));
Иначе
СтруктураОтвета.Вставить("error",Ошибка);
КонецЕсли;
Значение="";
Если СтруктураОтвета.Свойство("error") Тогда
ТекстОтвета = СтруктураОтвета.error;
Возврат Неопределено;
ИначеЕсли СтруктураОтвета.Свойство("warnings",Значение) Тогда
Для каждого Предупреждение из Значение Цикл
ТекстОтвета = ТекстОтвета+?(ЗначениеЗаполнено(ТекстОтвета), Символы.ПС, "") + Предупреждение.warning;
КонецЦикла;
Если СтрНайти(ТекстОтвета, "SZ150219-06")>0 Тогда
//МассивАдресов = Новый Массив;
//Для Каждого СтрокаТаблицы Из ПараметрыПисьма.Кому Цикл
// МассивАдресов.Добавить(СтрокаТаблицы.Адрес);
//КонецЦикла;
////СоответствиеАдресов = НайтиАдресаЭлектроннойПочтыВКонтактнойИнформации(МассивАдресов);
////Для каждого ОбъектКИ из СоответствиеАдресов Цикл
//// Если ЗначениеЗаполнено(ОбъектКИ.Значение) Тогда
//// Объект = ОбъектКИ.Значение.ПолучитьОбъект();
//// Объект.CRM_ОтписалсяОтEmailРассылок = Истина;
//// Объект.Записать();
//// КонецЕсли;
////КонецЦикла;
Возврат "Отписался";
КонецЕсли;
Возврат Неопределено;
ИначеЕсли СтруктураОтвета.Свойство("result",Значение) Тогда
//Если Значение.Количество()>0 Тогда
// Возврат Значение[0].id;
//Иначе
// Возврат Неопределено;
//КонецЕсли;
КонецЕсли;
КонецФункции
Функция ПолучитьЗначениеИзОтветаJSON(ФайлРезультата, ПрочитатьВСоответствие=Ложь)Экспорт
ЧтениеJSON=Новый ЧтениеJSON;
// ЧтениеJSON.УстановитьСтроку(ТекстJSON);
ЧтениеJSON.ОткрытьФайл(ФайлРезультата);
Значение=ПрочитатьJSON(ЧтениеJSON, ПрочитатьВСоответствие);
ЧтениеJSON.Закрыть();
УдалитьФайлы(ФайлРезультата);
Возврат Значение
КонецФункции
Функция ВыполнитьЗапрос(СтрокаЗапроса,Ресурс)
Сервер = "api.unisender.com/ru/api";
HTTP = Новый HTTPСоединение(Сервер,,,,,,Новый ЗащищенноеСоединениеOpenSSL);
ЗаголовокHTTP = Новый Соответствие();
ЗаголовокHTTP.Вставить("Content-Type", "application/x-www-form-urlencoded");
ЗаголовокHTTP.Вставить("Accept-Language", "ru");
ЗаголовокHTTP.Вставить("Accept-Charset", "utf-8");
ЗаголовокHTTP.Вставить("Content-Language", "ru");
ЗаголовокHTTP.Вставить("Content-Charset", "utf-8");
HTTPЗапрос = Новый HTTPЗапрос(Ресурс,ЗаголовокHTTP);
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаЗапроса,"UTF-8",ИспользованиеByteOrderMark.НеИспользовать);
ФайлРезультата = ПолучитьИмяВременногоФайла();
HTTP.ОтправитьДляОбработки(HTTPЗапрос, ФайлРезультата);
Возврат ФайлРезультата;
КонецФункции
(59) В частности вот этот код корректно формирует attachment
Для Каждого СтрокаТаблицы Из ПрикрепленныеФайлы Цикл
ФайлВложения=ПолучитьИзВременногоХранилища(СтрокаТаблицы.Файл);
ИмяВременногоФайла = КаталогВременныхФайлов()+СтрокаТаблицы.Имя;
ФайлВложения.Записать(ИмяВременногоФайла);
Текст = Новый ТекстовыйДокумент();
Текст.Прочитать(ИмяВременногоФайла, "ISO-8859-1", Символы.ПС);
Стр = Текст.ПолучитьТекст();
attachments=attachments+"&attachments["+ИмяВложения+"]="+КодироватьСтроку(Стр,
СпособКодированияСтроки.КодировкаURL, "ISO-8859-1");
КонецЦикла;
Показать
но ещё обратите внимание, что строка запроса, в которой есть вложения, передается в