Форум: "Прочее";
Текущий архив: 2009.08.16;
Скачать: [xml.tar.bz2];
ВнизBLOB->OLEConrtainer->File? Найти похожие ветки
← →
GRAND © (2009-06-18 14:36) [0]Здравствуйте, уважаемые! :)
Вот такая вот палка о двух концах у меня приключилась. Вобщем, имеется некий набор документов, хранимый в BLOB-полях таблицы с деревянной структурой (FB 1.5). Документы довольно разнообразны - там и Word, и PDF, и TIF и еще может быть все, что угодно. Когда я пытался отобразить содержимое документа в OLEContainer, то вылетала ошибка "Invalid stream format". Ну, думаю, нас не проведешь, мы не сдадимся - выгрузил все документы в файлы, после чего заставил OLEContainer эти файлы перечитать и зашарабанить их в базу заново (т.е. получается, что OLEContainer хавает только то, что когда-либо проходило через его "руки"). Все получилось, красота - документы хранятся, в контейнере отображаются, казалось бы, о чем еще мечтать? Ан нет, нарисовалась-таки проблемка. Захотел дать пользователю возможность выгружать любой документ из базы в произвольно заданный файл - и вот тут-то она ему и сказала. Файл создается, но никак не открывается потом родной для него программой. Причем, заметил, что если файл изначально был в формате Word 97-2003, то все работает и открывается, а вот *.docx, *.xlsx (MS Office 2007) и особенно *.pdf (львиная доля всех документов!) ни в какую. Получается, что я могу одно из двух: либо тупо хранить документы в базе без какой-либо возможности превью либо с превью, но без экспорта. Подскажите пожалуйста, как победить? Я понимаю, что формат данных OLE-контейнера от формата исходного файла отличается, но как же его все-таки заставить сохранять файлы в их первозданном виде?
P.S. SaveToFile, SaveAsDocument - результат один и тот же.
← →
Игорь Шевченко © (2009-06-18 14:46) [1]Знакомый вопрос :)
Blob save to stream не помогает ?
← →
GRAND © (2009-06-18 14:49) [2]
> Blob save to stream не помогает ?
Привет, Игорь! А какой смысл блоб сохранять в потоке, если содержимое в конечном итоге нужно выплюнуть в файл (корректный файл)? Ну TMemoryStream, допустим, позволит сохранить себя в файле, но формат-то этого файла будет все равно не тот, который нужен.
← →
Andy BitOff © (2009-06-18 14:51) [3]
> GRAND © (18.06.09 14:49) [2]
> но формат-то этого файла будет все равно не тот, который нужен
Это почему? Уже проверил?
← →
GRAND © (2009-06-18 14:53) [4]Да, уже проверил.
← →
Игорь Шевченко © (2009-06-18 14:56) [5]GRAND © (18.06.09 14:49) [2]
Привет, Володя!
Почему не тот формат ? FB у меня сейчас нету, а в оракле я тебе могу пример набросать :)
← →
GRAND © (2009-06-18 15:00) [6]
> Почему не тот формат ? FB у меня сейчас нету, а в оракле
> я тебе могу пример набросать :)
Вообще-то оно абсолютно фиолетово, в какой базе это все хранится, и FB тут не при чем. Вопрос заключается в отличии форматов Ole-контейнера, потока и исходного файла. Если файл затянуть в блоб as is, то он не покажется в контейнере (превью не будет), а если протащить его через жернова контейнера, то его формат изменится! И потом выкинутые из блоба снова в файл данные уже бесполезны, т.к. не открываются. Поэтому, Игорь, если ты сможешь набросать примерчик, где все то, что нужно, будет работать хоть в Оракле, хоть в Постгре, то буду тебе очень благодарен!
← →
GRAND © (2009-06-18 15:03) [7]Вот так файл затягивается в базу через контейнер:
Var
St : TStream;
begin
St:=DM.tbClDocs.CreateBlobStream(DM.tbClDocsCD_BODY,bmReadWrite);
If OpenDialog1.Execute Then
Begin
cxButtonEdit1.Text:=OpenDialog1.FileName;
Screen.Cursor:=crHourGlass;
If Not (DM.tbClDocs.State In [dsInsert, dsEdit]) Then DM.tbClDocs.Edit;
OLEContainer1.CreateObjectFromFile(OpenDialog1.FileName,False);
OLEContainer1.SaveToStream(St);
DM.tbClDocsCD_STATE.AsInteger:=1;
DM.tbClDocsCD_EXT.AsString:=ExtractFileExt(OpenDialog1.FileName);
Screen.Cursor:=crDefault
End;
St.Free
end;
OLEContainer1.SaveToStream(St) - это одновременно и сохранение файла в блоб. Далее, уже за пределами этого обработчика, производится Post и вуа-ля.
← →
Игорь Шевченко © (2009-06-18 16:23) [8]Насчет примера - у меня не получается загрузить файл в OleContainer, причем, даже в примере из Demos - приложение висит. Оказывается, проблема известная и на experts-exchange не решенная.
Сам пример:
1. Таблица в базе:CREATE TABLE files_data (
name VARCHAR2(40) NOT NULL,
data BLOB,
CONSTRAINT files_data_pk PRIMARY KEY(name) USING INDEX TABLESPACE hs_idx
) TABLESPACE hs_dat
/
2. Главная формаunit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, Grids, DBGridEh, OleCtnrs;
type
TfMain = class(TForm)
MainMenu1: TMainMenu;
File1: TMenuItem;
Open1: TMenuItem;
Saveas1: TMenuItem;
Preview1: TMenuItem;
N1: TMenuItem;
Exit1: TMenuItem;
Grid: TDBGridEh;
OpenDialog1: TOpenDialog;
SaveDialog1: TSaveDialog;
OleContainer1: TOleContainer;
procedure Exit1Click(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure Open1Click(Sender: TObject);
procedure Saveas1Click(Sender: TObject);
procedure Preview1Click(Sender: TObject);
procedure OleContainer1Activate(Sender: TObject);
end;
var
fMain: TfMain;
implementation
uses
data;
{$R *.dfm}
procedure TfMain.Exit1Click(Sender: TObject);
begin
Close;
end;
procedure TfMain.FormShow(Sender: TObject);
begin
OleContainer1.Visible := false;
Grid.DataSource := dm.dsData;
end;
procedure TfMain.OleContainer1Activate(Sender: TObject);
begin
OleContainer1.Modified := True;
end;
procedure TfMain.Open1Click(Sender: TObject);
begin
with OpenDialog1 do
if Execute then
dm.LoadFile(FileName);
end;
procedure TfMain.Preview1Click(Sender: TObject);
begin
with OpenDialog1 do
if Execute then
begin
OLEContainer1.CreateObjectFromFile(dm.GetSavedTempFileName, false);
OleContainer1.Visible := true;
end;
end;
procedure TfMain.Saveas1Click(Sender: TObject);
begin
with SaveDialog1 do
begin
FileName := Grid.DataSource.DataSet.FieldByName("name").AsString;
if Execute then
dm.SaveFile(FileName);
end;
end;
end.
датамодуль:unit data;
interface
uses
SysUtils, Classes, DB, hsOraCursor, hsOraDataSet, hsOraDatabase;
type
Tdm = class(TDataModule)
db: ThsOraDatabase;
qData: ThsOraDataSet;
qDataNAME: TStringField;
qDataDATA: TOraMemoField;
dsData: TDataSource;
qInsert: ThsOraDataSet;
qUpdateBlob: ThsOraDataSet;
procedure DataModuleCreate(Sender: TObject);
public
procedure LoadFile (const FileName: string);
procedure SaveFile (const FileName: string);
function GetSavedTempFileName: string;
end;
var
dm: Tdm;
implementation
uses
Windows;
{$R *.dfm}
procedure Tdm.DataModuleCreate(Sender: TObject);
begin
db.Open;
qData.Open;
end;
function Tdm.GetSavedTempFileName: string;
var
L: Integer;
F: TFileStream;
begin
Setlength(Result, MAX_PATH);
L := GetTempPath(MAX_PATH, PChar(Result));
if L > 0 then
begin
SetLength(Result, L);
Result := IncludeTrailingPathDelimiter(Result) +
qData.FieldByName("name").AsString;
F := TFileStream.Create(Result, fmCreate);
try
TBlobField(qData.FieldByName("data")).SaveToStream(F);
finally
F.Free;
end;
end;
end;
procedure Tdm.LoadFile(const FileName: string);
var
F: TFileStream;
N, E: string;
begin
E := ExtractFileExt(FileName); //. тъы■ўхэр
N := Copy(ChangeFileExt(ExtractFileName(FileName), ""), 1, 40-Length(E))+E;
qInsert.ParamByName("name").AsString := N;
qInsert.ExecSQL;
F := TFileStream.Create(FileName, fmOpenRead);
try
qUpdateBlob.ParamByName("name").AsString := N;
qUpdateBlob.ParamByName("data").LoadFromStream(F, ftBlob);
qUpdateBlob.ExecSQL;
db.Commit;
qData.Close;
qData.Open;
finally
F.Free;
end;
end;
procedure Tdm.SaveFile(const FileName: string);
var
F: TFileStream;
begin
F := TFileStream.Create(FileName, fmCreate);
try
TBlobField(qData.FieldByName("data")).SaveToStream(F);
finally
F.Free;
end;
end;
end.
запросы:
qData.SQL - "SELECT name,data FROM files_data ORDER BY name"
qInsert.SQL - "INSERT INTO files_data (name) VALUES (:name)"
qUpdateBlob.SQL - "UPDATE files_data SET data = :data WHERE name = :name
RETURNING data INTO :data"
Сохраненный файл до бита идентичен загруженному
← →
GRAND © (2009-06-19 10:05) [9]Игорь, спасибо тебе большое за проделанную работу! Вчера не смог отреагировать, т.к. был срочно выдернут на совещание, продлившееся до глубокого вечера. Сегодня попробовал действовать по твоей схеме и напоролся на проблему с OLEContainer, которую уже проходил ранее. Проблема вот в чем: при организации превью файл через TFileStream создается, он железно лежит там, где ему и положено лежать, своей родной программой открывается, но при попытке грузануть его в контейнер через CreateObjectFromFile вылетает EOleSysError: "Не удается найте %1". Что это за хрень, я не знаю, предположил только лишь, что это чем-то похоже на запуск чего-то с параметром (как в bat"ах пишут, помнишь? %1 %2...). Вот как с этим быть? У тебя контейнер все показывает и ничего эдакого не выдает?
← →
Игорь Шевченко © (2009-06-19 10:37) [10]GRAND © (19.06.09 10:05) [9]
Володя, у меня не получается вообще загрузить файл в контейнер :) Никакой, хоть с диска, хоть из базы.
ситуация аналогичная
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_23747098.html
← →
GRAND © (2009-06-19 10:58) [11]
> Володя, у меня не получается вообще загрузить файл в контейнер
> :) Никакой, хоть с диска, хоть из базы.
Вон, выше я привел код, где файл грузится в контейнер :)
← →
GRAND © (2009-06-19 11:03) [12]Наверное придется-таки грузить файл в 2 блоба - один будет хранить его в олешном виде, а другой в исходном. ППЦ!!! :)))
← →
GRAND © (2009-06-19 11:11) [13]Еще глюк: иногда при попытке открыть филе из контейнера (по дабл-клику) вылазит ошибка "Не удается открыть файл при помощи специального имени". Это еще че, блин, такое?
← →
Игорь Шевченко © (2009-06-19 11:32) [14]GRAND © (19.06.09 10:58) [11]
Ты ссылку-то прочитай :)
← →
GRAND © (2009-06-19 11:55) [15]
> Ты ссылку-то прочитай :)
Ну и? Беру спокойно pdf (не MS Office, правда?), гружу и вижу его в контейнере!
← →
Игорь Шевченко © (2009-06-19 12:13) [16]GRAND © (19.06.09 11:55) [15]
А я не вижу, я зависаю. Об чем написано в ссылке "on some pc"
Потому не могу тебя проконсультировать по поведению OleContainer. Я знаю, что выгруженный из базы в моем примере файл идентичен загруженному (сравнивалось по fc /b), чего тебе тоже рекомендую - сравнить, что выходит из OleContainer, то, что сохраняется твоей выгрузкой из базы и то, что загружается в базу.
← →
GRAND © (2009-06-19 12:57) [17]
> А я не вижу, я зависаю. Об чем написано в ссылке "on some
> pc"
И если написать обработчик так, как у меня, тоже виснешь?
← →
Игорь Шевченко © (2009-06-19 13:06) [18]GRAND © (19.06.09 12:57) [17]
Я висну даже на примере из Demos
← →
GRAND © (2009-06-19 14:20) [19]Как все запущено! :)
Ну, а у меня наконец-то все заработало, ура! Теперь вот чешу репу, возможен ли в контейнере мультистраничный просмотр или ну его на фиг?
Страницы: 1 вся ветка
Форум: "Прочее";
Текущий архив: 2009.08.16;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.011 c