Имя: Пароль:
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);
Не знаю правда насколько это правильное решение, но вроде как все работает. Прошу проконсультировать по степени кривости такого подхода.
Проблемы невозможно решaть нa том же уровне компетентности, нa котором они возникaют. Альберт Эйнштейн