原文网址: http://www.yourblog.org/Data/20061/411359.html 日期:2006年1月15日 星期日 天气:晴朗 作者:ThornBird 通过SQL Server在服务器上存取文件 发表:2006-1-15 15:26:05 出处:你的博客网(yourblog.org)
--------------------------------------------------------------------------------
前些天改公司的程序,发现员工基本资料表中的照片字段竟是字符型,只保存照片的路径。我们的程序一般是用远程桌面访问,或是把程
序所在目录映射为本地盘并运行程序。这样一来,图片只能放在服务器上才能进行显示、打印,且如果采取映射本地盘的方式,每个客户端应
该都必须映射为相同的本地盘(或者把照片放在程序所在目录下,保存相对路径)。于是我把照片字段改成text类型,把文件存储到数据库中
,不过一个同事不同意我的做法,于是只好作罢。但后来我想到其实可以把照片“上传”到服务器上,需要使用时再“下载”到本地,然后数
据库中保存文件在服务器上的实际路径。通过查资料,我知道了可以用 sp_makewebtask 存储过程把查询结果保存到服务器上,遗憾的是它是
保存为网页的格式,而不能把文件照原样保存到服务器上。不过无所谓了,只要“下载”时再对文件结构进行分析就可以了,这样一来就可以
实现“上传”的功能了。至于“下载”,可以用 BULK INSERT 语句来实现。 我的思路是这样的:把文件进行编码后保存到 SQL Server 的临时表中,然后执行 sp_makewebtask 存储过程保存文件;使用“上传”的
文件时则可以用 BULK INSERT 语句把文件存入临时表中,然后再通过查询得到文件的全部内容,然后进行分析和解码后进行保存。上面两个步
骤都需要有足够的权限。这就是我的 ServerFileAccess 类的基本思路,这个类主要有下面几个方法:
SetConnectString 设置连接字符串 SetConnectHandle 设置连接句柄 Connect 与 SQL Server 建立连接 Disconnect 断掉连接 UploadFile 把客户端的文件“上传”到服务器上 GetFileFromServer 获取服务器上的文件 GetUploadFileFromServer 获取之前“上传”到服务器上的文件 DownloadFile “下载”服务器上的指定文件到本地 DownloadUploadFile “下载”之前“上传”到服务器上的文件到本地
下面是 ServerFileAccess 类的代码及演示: ServerFileAccess.prg DEFINE CLASS ServerFileAccess AS Custom
PROTECTED ConnectString PROTECTED ConnectHandle PROTECTED Connected PROTECTED FLAG_START PROTECTED FLAG_END PROTECTED ROWTERMINATOR PROCEDURE Init THIS.ConnectString = "" THIS.ConnectHandle = -1 THIS.Connected = .F. THIS.FLAG_START = "<<START>>" THIS.FLAG_END = "<<END>>" THIS.ROWTERMINATOR = CHR(13) ENDPROC PROCEDURE Destroy IF THIS.Connected = .T. THIS.Disconnect() ENDIF ENDPROC PROCEDURE SetConnectString LPARAMETERS cServer, cDatabase, cUserId, cPassword THIS.ConnectString = "Driver=SQL Server;" + ; "Server=" + cServer + ";" + ; "Database=" + cDatabase + ";" + ; "Uid=" + cUserId + ";" + ; "Pwd=" + cPassword ENDPROC PROCEDURE SetConnectHandle LPARAMETERS nConnectHandle THIS.ConnectHandle = nConnectHandle ENDPROC PROCEDURE Connect PRIVATE nDispLogin nDispLogin = SQLGETPROP(0, "DispLogin") = SQLSETPROP(0, "DispLogin", 3) IF THIS.ConnectHandle > 0 RETURN .T. ENDIF THIS.ConnectHandle = SQLSTRINGCONNECT(THIS.ConnectString) = SQLSETPROP(0, "DispLogin", nDispLogin) IF THIS.ConnectHandle > 0 THIS.Connected = .T. RETURN .T. ENDIF RETURN .F. ENDPROC PROCEDURE Disconnect PRIVATE lReturnValue lReturnValue = .T. THIS.ConnectString = "" TRY = SQLDISCONNECT(THIS.ConnectHandle) CATCH lReturnValue = .F. ENDTRY THIS.ConnectHandle = -1 Connected = .F. RETURN lReturnValue ENDPROC PROCEDURE UploadFile LPARAMETERS cClientFile, cServerFile PRIVATE lReturnValue, nReturnValue, cTableName, cSQL, cDrop, cFileData, cRandKey lReturnValue = .F. nReturnValue = -1 cTableName = "##" + SYS(2015) cSQL = [CREATE TABLE ] + ; cTableName + ; [ (RandKey char(8) NULL, FileData text NULL)] cDrop = [DROP TABLE ] + cTableName cFileData = THIS.FLAG_START + ; STRCONV(FILETOSTR(cClientFile), 15) + ; THIS.FLAG_END cRandKey = SYS(3) = SQLEXEC(THIS.ConnectHandle, cSQL) cSQL = [INSERT INTO ] + cTableName + ; [ (RandKey, FileData)] + ; [ VALUES] + ; [ (’] + cRandKey + [’, ’] + cFileData + [’)] nReturnValue = SQLEXEC(THIS.ConnectHandle, cSQL) IF nReturnValue < 0 = SQLEXEC(THIS.ConnectHandle, cDrop) RETURN lReturnValue ENDIF cSQL = [EXECUTE master..sp_makewebtask ] + ; ["] + cServerFile + [", ] + ; ["SELECT FileData FROM ] + cTableName + ; [ WHERE RandKey = ’] + cRandKey + [’"] nReturnValue = SQLEXEC(THIS.ConnectHandle, cSQL) IF nReturnValue > 0 lReturnValue = .T. ENDIF = SQLEXEC(THIS.ConnectHandle, cDrop) RETURN lReturnValue ENDPROC PROCEDURE GetFileFromServer LPARAMETERS cServerFile PRIVATE cFileData, nReturnValue, cTableName, cSQL, cDrop, ; cCurrentAlias, cAlias, i cFileData = "" nReturnValue = -1 cTableName = "##" + SYS(2015) cSQL = [CREATE TABLE ] + ; cTableName + ; [ (FileData text NULL)] cDrop = [DROP TABLE ] + cTableName nReturnValue = SQLEXEC(THIS.ConnectHandle, cSQL) IF nReturnValue < 0 RETURN cFileData ENDIF cSQL = [BULK INSERT ] + cTableName + ; [ FROM ’] + cServerFile + [’] + ; [ WITH (ROWTERMINATOR = ’] + ; THIS.ROWTERMINATOR + [’)] nReturnValue = SQLEXEC(THIS.ConnectHandle, cSQL) IF nReturnValue < 0 = SQLEXEC(THIS.ConnectHandle, cDrop) RETURN cFileData ENDIF cCurrentAlias = ALIAS() cAlias = SYS(2015) cSQL = [SELECT FileData FROM ] + cTableName nReturnValue = SQLEXEC(THIS.ConnectHandle, cSQL, cAlias) = SQLEXEC(THIS.ConnectHandle, cDrop) IF nReturnValue < 0 RETURN cFileData ENDIF SELECT (cAlias) GO TOP SCAN cFileData = cFileData + ; IIF(ISNULL(FileData) = .T., "", ALLTRIM(FileData)) + ; IIF(RECNO() = RECCOUNT(), "", THIS.ROWTERMINATOR) ENDSCAN USE IN (cAlias) IF EMPTY(cCurrentAlias) = .F. SELECT (cCurrentAlias) ENDIF RETURN cFileData ENDPROC PROCEDURE GetUploadFileFromServer LPARAMETERS cServerFile PRIVATE cFileData, nStart, nLength cFileData = "" cFileData = THIS.GetFileFromServer(cServerFile) IF EMPTY(cFileData) = .T. RETURN cFileData ENDIF nStart = AT(THIS.FLAG_START, cFileData) + LEN(THIS.FLAG_START) nLength = AT(THIS.FLAG_END, cFileData) - nStart cFileData = SUBSTR(cFileData, nStart, nLength) cFileData = STRCONV(cFileData, 16) RETURN cFileData ENDPROC PROCEDURE DownloadFile LPARAMETERS cServerFile, cClientFile PRIVATE cFileData cFileData = THIS.GetFileFromServer(cServerFile) = STRTOFILE(cFileData, cClientFile) RETURN .T. ENDPROC PROCEDURE DownloadUploadFile LPARAMETERS cServerFile, cClientFile PRIVATE cFileData cFileData = THIS.GetUploadFileFromServer(cServerFile) = STRTOFILE(cFileData, cClientFile) RETURN .T. ENDPROC
ENDDEFINE
ServerFileAccess_Demo.prg SET PROCEDURE TO ServerFileAccess.prg oServerFileAccess = CREATEOBJECT("ServerFileAccess") oServerFileAccess.SetConnectString("127.0.0.1", "master", "sa", "123456") oServerFileAccess.Connect()
*-- 演示 UploadFile 方法 cSource = GETFILE("", "上传文件(&F):", "选择", 0, "请选择要上传到服务器上的文件") cTarget = ALLTRIM(INPUTBOX("保存路径(含文件名):", "请输入上传路径及目标文件名")) ? oServerFileAccess.UploadFile(cSource, cTarget)
*-- 演示 DownloadUploadFile 方法 cFileName = PUTFILE("保存文件(&F)", "", JUSTEXT(cSource)) ? oServerFileAccess.DownloadUploadFile(cTarget, cFileName)
oServerFileAccess.Disconnect() |