用Delphi在Oracle的BLOB字段中存取Excel文件 (100分)

L

libra_l

Unregistered / Unconfirmed
GUEST, unregistred user!
请高手指教:
我用Delphi开发的一个软件需要在Oracle的Blob字段中存取Excel文件,
保存文件到库中没有问题,但是确无法打开从库中读取的文件,打开文件是,
系统提示如下信息:
“不能访问MyFile.xls,该文件可能是只读的,或者你要访问的位置是只读的,
或者文件所在的服务器没有相应。”
我试过的方法包括:
1:直接用Blob字段读取,例如:
存:TBLobField(MyBlobField).LoadFromFile(MyFileName)
读:TBlobField(MyBlobField).SaveToFile(MyFileName)
2:利用文件流,例如:
存:FileStream.LoadFromFile(MyFileName);
TBlobField(MyBlobField).LoadFromStream(FileStream);
读:TBlobField(MyBlobField).SaveToStream(FileStream);
FileStream.SaveToFile(MyFileName);
3:利用文件流和Blob数据流
存:FileStream := TFileStream.Create(MyFileName,fmOpenRead);
FileStream.Seek(0,soFromBeginning);
Buffer := AllocMem(FieldStream.Size+1);
FileStream.Read(Buffer^,FileSize);
BlobStream.Create(MyBlobField,bmWrite);
BlobStream.Write(Buffer^,FileSize);
读: ......
FileStream := TFileStream.Create(MyFileName,fmCreate);
FieldStream:= TBlobStream.Create(TBlobField(MyBlobField,bmRead);
Buffer := AllocMem(FieldStream.Size+1);
FieldStream.Read(Buffer^,FieldStream.Size+1);
FileStream.Write(Buffer^,FieldStream.Size+1);
......
以上三种方法读出的文件现象都一样
急用,请高手指教
 
try this:

var
Buffer:String;
FileName:String;
try

FileStream:=TFileStream.Create(FileName,fmOpenRead or fmShareDenyWrite)
SetLength(Buffer,FileStream.Size);
FileStream.Read(Pointer(Buffer)^, FileStream.Size);
BlobStream.Create(MyBlobField,bmWrite);
BlobStream.Write(Pointer(Buffer)^, FileSize);
except end;

我以前曾经试过,用1,2的方法不能直接LoadFromFile,这样有问题,后来没有继续研究,
我们一起看看怎样能使用1,2的方法.
 
读到数据库之后,再保存为另一个文件,看看,大小是不是一样?
 
try another way:

//To write to Blob;
procedure TForm1.Button1Click(Sender: TObject);
var
blob: TBlobStream;
begin
blob := myDataset.CreateBlobStream(myDataset.FieldByName('myBLOB_test'), bmWrite);
try
blob.Seek(0, soFromBeginning);
fs := TFileStream.Create('E:/myFile.xls', fmOpenRead or
fmShareDenyWrite);
try
blob.CopyFrom(fs, fs.Size)
finally
fs.Free
end;
finally
blob.Free
end;
end;

// To load from BLOB:
procedure TForm1.Button1Click(Sender: TObject);
var
blob: TBlobStream;
begin
blob := myDataset.CreateBlobStream(myDataset.FieldByName('myBLOB_test'), bmRead);
try
blob.Seek(0, soFromBeginning);
with TFileStream.Create('E:/myFile.xls', fmCreate) do
try
CopyFrom(blob, blob.Size)
finally
Free
end;
finally
blob.Free
end;
end;
 
我在Sql Server中实现了同样的功能,但没有错啊/
在数据库中直接按流的格式存的。主要是内存流,TMemostream/
 
楼上的各位,你们好,非常感谢你们的答复,但是你们所说的我都试过,效果都一样。另外
magiclynn所说的我也试了,在Blob.CopyFrom(fs,fs.size)时出现异常"Stream Read Error",
不知道还有没有好的办法。
 
用这种试试,写数据库代码如下:
with query1 do
begin
sSQL:=
'insert into Createdreport '+
'(setid,year,id,title,eid,enterprisename,month,contain,'+
' userid,username,inputdate) '+
' values:)SetID,:Year,:Id,:title,:eid,:enterprisename,'+
' :month,:contain,:userid,:username,:inputdate)';
SQL.Text :=sSQL;
ParamByName('SetID').AsString := IntToStr(mSetID);
ParamByName('Year').AsString := IntToStr(mYear);
ParamByName('ID').AsString:='1000';
ParamByName('Title').AsString:='';
ParamByName('EID').AsString:=mEID;
ParamByName('EnterpriseName').AsString:=mEName;
ParamByName('Month').AsString:='1';//m_Month;
ParamByName('UserID').AsString:=mUserID;
ParamByName('UserName').AsString:=mUserName;
ParamByName('InputDate').AsDateTime:=Now();
ParamByName('Contain').LoadFromFile('数据库文件.CLL',ftBlob);
ExecSQL;
end;
 
读数据库中的Blob,保存成文件。
sSql:= 'select * from CreatedReport where SetID=' + inttostr(mSetID)
+ ' and Year=' + inttostr(mYear) + ' and EID=''' + mEID + ''''
+ ' and ID=''1000'' and month='+#39+'1'+#39;
with Dm_MainForm.Query_A do
begin
Close;
Sql.Text := sSql;
Open;
end;

if Not Dm_MainForm.Query_A.Eof then
begin
TBlobField(Dm_MainForm.Query_A.FieldByName('Contain')).SaveToFile('数据库临时存储文件.CLL');
end;
 
非常感谢各位的参与,虽然没有得到准确的答案,但是也得到了某些启发,
感受到了大家的积极参与。
目前只好采用了变通的办法,首先将文件压缩,然后再保存,取出时再解压。问题基本上
得到解决。

最后要说明的是:该问题是针对Oracle数据库,对于其他数据库,比如Sybase等,
就不存在这个问题。
 
顶部