Имя: Пароль:
1C
1С v8
Сохранение PDF-файла из сторонней SQL базы.
0 sergejkonet
 
03.02.14
09:57
Добрый день!

Нужно реализовать сохранение или открытие pdf-файлов из сторонней sql-базы. в sql хранится одна таблица с двумя параметрами: номер и само изображение(бинарник), К базе подключается, запись нужную находит, а вот открыть не получается. Выдает ошибку "Неправильный путь к файлу '25 50 44 46 2D 31 2E....." и дальше содержание бинарника. Я так пониманию нужно указать в ОписанииПердаваемогоФайла, другие параметры. Но какие что-то не пойму. Пробовал ссылку на ВнешниеИсточникиДанных, не проходит. Да. при нажатии кнопки запускающей процедуру, предлагает сохранить или открыть, при сохранении выдает ошибку, но в папке qw появляется файл pdf 0байт..Прошу подсказать с решением данной проблемы.


Процедура VievНажатие(Элемент)
    
НомерЧертежа = СокрЛП(ЭлементыФормы.СправочникСписок.ТекущаяСтрока.Код);

        Параметры = ВнешниеИсточникиДанных.Чертежи.ПолучитьОбщиеПараметрыСоединения();
Параметры.АутентификацияСтандартная = Истина;
Параметры.ИмяПользователя = "sa";
Параметры.Пароль = "1";
Параметры.СтрокаСоединения = "DRIVER={SQL Server};SERVER=(local);UID=sa;PWD=1;DATABASE=Fotos";
Параметры.СУБД = "MSSQLServer";

ВнешниеИсточникиДанных.Чертежи.УстановитьОбщиеПараметрыСоединения(Параметры);
ВнешниеИсточникиДанных.Чертежи.УстановитьПараметрыСоединенияПользователя(ИмяПользователя(), Параметры);
ВнешниеИсточникиДанных.Чертежи.УстановитьПараметрыСоединенияСеанса(Параметры);


ВнешниеИсточникиДанных.Чертежи.УстановитьСоединение();
Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ
|    dbo_Chertezhi.image
|ИЗ
|    ВнешнийИсточникДанных.Чертежи.Таблица.dbo_Chertezhi КАК dbo_Chertezhi ГДЕ dbo_Chertezhi.number = &НомерЧертежа"  ;
Запрос.УстановитьПараметр("НомерЧертежа",НомерЧертежа);

Рез=Запрос.Выполнить().Выбрать();
Если Рез.Следующий() Тогда
ПолучаемыйФайл = Новый ОписаниеПередаваемогоФайла("D:\qw\" + "scan.pdf", Рез.image);
    ПолучаемыеФайлы = Новый Массив;
    ПолучаемыеФайлы.Добавить(ПолучаемыйФайл);
       ПолученныеФайлы = Новый Массив;
     ПолучитьФайлы(ПолучаемыеФайлы, ПолученныеФайлы)  ;

    КонецЕсли;

КонецПроцедуры
1 sapphire
 
03.02.14
10:00
видимо, надо через ADO DB Stream :)
2 sergejkonet
 
03.02.14
10:02
Так. пойду гуглить. Но если не затруднит, можно немного подробнее описать что к чему.
3 sapphire
 
03.02.14
10:06
(2) Че там описывать - открываешь поток, сохраняешь в файл.
4 golden-pack
 
03.02.14
10:07
StreamOut = Новый COMОбъект("ADODB.Stream");
    StreamOut.Type = 1;
    StreamOut.Mode = 3; //Нужны и чтение и запись.
    
    StreamOut.Open(); //Открыли на чтение и запись
    StreamOut.Write(COMSafeArray);
    StreamOut.SaveToFile(ИмяВременногоФайла, 2);
    StreamOut.Close();
5 sergejkonet
 
03.02.14
13:27
Что-то я торможу. не могу никак разобраться что куда. Пытался вставить поток но при выполнении вылетает ошибка
"Ошибка при вызове метода контекста (Write)
    Stream.Write(p);
по причине:
Произошла исключительная ситуация (ADODB.Stream): Аргументы имеют неверный тип, выходят за пределы допустимого диапазона или вступают в конфликт друг с другом."
Может есть у кого-то рабочие примеры, что бы можно было разбираться по аналогии, что куда, или здесь ткните пальцем. А то в инете в основном обще примеры, и внять им не получается:(


Процедура VievНажатие(Элемент)
    
НомерЧертежа = СокрЛП(ЭлементыФормы.СправочникСписок.ТекущаяСтрока.Код);

        Параметры = ВнешниеИсточникиДанных.Чертежи.ПолучитьОбщиеПараметрыСоединения();
Параметры.АутентификацияСтандартная = Истина;
Параметры.ИмяПользователя = "sa";
Параметры.Пароль = "1";
Параметры.СтрокаСоединения = "DRIVER={SQL Server};SERVER=(local);UID=sa;PWD=1;DATABASE=Fotos";
Параметры.СУБД = "MSSQLServer";

ВнешниеИсточникиДанных.Чертежи.УстановитьОбщиеПараметрыСоединения(Параметры);
ВнешниеИсточникиДанных.Чертежи.УстановитьПараметрыСоединенияПользователя(ИмяПользователя(), Параметры);
ВнешниеИсточникиДанных.Чертежи.УстановитьПараметрыСоединенияСеанса(Параметры);

ВнешниеИсточникиДанных.Чертежи.УстановитьСоединение();
Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ
|    dbo_Chertezhi.image
|ИЗ
|    ВнешнийИсточникДанных.Чертежи.Таблица.dbo_Chertezhi КАК dbo_Chertezhi ГДЕ dbo_Chertezhi.number = &НомерЧертежа"  ;
Запрос.УстановитьПараметр("НомерЧертежа",НомерЧертежа);

Рез=Запрос.Выполнить().Выбрать();

  
Stream=Новый COMОбъект("ADODB.Stream");
Stream.Mode=3;
Stream.Type=1;

    Stream.Open();
    p=image;
    Stream.Write(p);
    ИмяРисунка="pic"+НомерЧертежа+".pdf";
    Stream.SaveToFile(КаталогВременныхФайлов()+ИмяРисунка,2);
    Stream.Close();

  
ВрХран=ПоместитьВоВременноеХранилище(Stream);
Если Рез.Следующий() Тогда

ПолучаемыйФайл = Новый ОписаниеПередаваемогоФайла("D:\qw\" + "scan.pdf", ВрХран );
    ПолучаемыеФайлы = Новый Массив;
    ПолучаемыеФайлы.Добавить(ПолучаемыйФайл);
       ПолученныеФайлы = Новый Массив;
     ПолучитьФайлы(ПолучаемыеФайлы, ПолученныеФайлы)  ;

    КонецЕсли;



КонецПроцедуры
6 sergejkonet
 
04.02.14
08:20
Вот что получилось в новом запросе:
Процедура VievНажатие(Элемент)
    
НомерЧертежа = СокрЛП(ЭлементыФормы.СправочникСписок.ТекущаяСтрока.Код);

стрПодключения = "Data Source=MICROSOF-B31904;Initial Catalog=Fotos; Persist Security Info=True;User ID=sa; Password=1";
Connection = Новый COMОбъект("ADODB.Connection");
Connection.Provider = "SQL Server Native Client 10.0";    
Connection.ConnectionString = стрПодключения;

Попытка
Connection.Open();
Сообщить ("Соединение установлено" );
Исключение
Сообщить ("Проблемы с подключением к InterBase" );
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;

Stream = Новый COMОбъект("ADODB.Stream");
Stream.Type = 1;
Stream.Open();
RecordSet = Новый COMОбъект("ADODB.RecordSet");
RecordSet.CursorLocation = 3;
RecordSet.LockType = 2;
Запрос = "SELECT image FROM dbo.Chertezhi WHERE number = НомерЧертежа";
RecordSet.Open(Запрос,Connection);
RecordSet.MoveFirst();
Stream.Write(RecordSet.Fields("image").Value);
ИмяФайла = RecordSet.Fields("number").Name;
фрис = КаталогВременныхФайлов() + ИмяФайла + ".pdf";

Stream.SaveToFile(фрис);
ЗапуститьПриложение(фрис);
Stream.Close();
RecordSet.Close();
Файл = Новый ДвоичныеДанные(фрис);
УдалитьФайлы(фрис);
Connection.Close();
КонецПроцедцры

Но здесь новая проблема. Как обяснить SQL что переменная НомерЧертежа, заданная первой строкой и Значение НомерЧертежа в самом запросе, есть одно и то же. 1С при отладке это понимает, присваиет нужное значение, но вот SQL выдает ошибку: Ошибка при вызове метода контекста (Open)
RecordSet.Open(Запрос,Connection);
по причине:
Произошла исключительная ситуация (Microsoft SQL Server Native Client 10.0): Недопустимое имя столбца "НомерЧертежа".

Но здесь и в самом запросе очевидно какой-то косяк, т.к. когда подставлял в запрос значение номера, существующего в базе он ругался что не может найти такую запись в таблице.
7 shuhard
 
04.02.14
08:29
(6)[SELECT image FROM dbo.Chertezhi WHERE number = НомерЧертежа]
феерично
8 sergejkonet
 
04.02.14
08:36
(7) О да(((Я просто реально впервые с 1С сталкиваюсь, поэтому извините за такие тупые ошибки и если можно подскажите как поправить.
9 sergejkonet
 
04.02.14
10:38
Так-с. докопался. Вот этот код робит.

Процедура VievНажатие(Элемент)
НомерЧертежа = СокрЛП(ЭлементыФормы.СправочникСписок.ТекущаяСтрока.Код);

стрПодключения = "Data Source=MICROSOF-B31904;Initial Catalog=Fotos; Persist Security Info=True;User ID=sa; Password=1";
Connection = Новый COMОбъект("ADODB.Connection");
Connection.Provider = "SQL Server Native Client 10.0";    
Connection.ConnectionString = стрПодключения;

Попытка
Connection.Open();
Сообщить ("Соединение установлено" );
Исключение
Сообщить ("Проблемы с подключением к InterBase" );
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;

Stream = Новый COMОбъект("ADODB.Stream");
Stream.Type = 1;
Stream.Open();
RecordSet = Новый COMОбъект("ADODB.RecordSet");
RecordSet.CursorLocation = 3;
RecordSet.LockType = 2;
Запрос = "SELECT [image] FROM [Fotos].[dbo].[Chertezhi] WHERE [number] = '" + НомерЧертежа + "'";
RecordSet.Open(Запрос,Connection);
RecordSet.MoveFirst();
Stream.Write(RecordSet.Fields("image").Value);
ИмяФайла = НомерЧертежа;
фрис = КаталогВременныхФайлов() + ИмяФайла + ".pdf";

Stream.SaveToFile(фрис);
ЗапуститьПриложение(фрис);
Stream.Close();
RecordSet.Close();
Файл = Новый ДвоичныеДанные(фрис);
УдалитьФайлы(фрис);
Connection.Close();

Если исполнять весь код, то открывается пустой пдф-ридер, если же удалить последние 3 строчки, то открывается с изображением. все как надо. все открывается,но как удалять из временной папки после закрытий пдф-ридера? Есть какие-то идеи может?
10 sergejkonet
 
04.02.14
11:02
Было бы допустимо просто при совпадении имен перезаписывать файл, т.к. все файлы будут во временной папке, а компы выключаются каждый день, то пользователи немного места отхватят, я так понимаю здесь нужно указать параметр какой-то. но где и какой?
11 sergejkonet
 
04.02.14
11:59
Решилась проблема введением параметра adSaveCreateOverWrite, но правда перед этим пришлось присвоить ему значение 2.
adSaveCreateOverWrite = 2;
Stream.SaveToFile(фрис, adSaveCreateOverWrite);
Не знаю правда насколько это правильное решение, но вроде как все работает. Прошу проконсультировать по степени кривости такого подхода.