这是我返回@v_buffer
变量的过程的一部分。
问题是,我要上传的文件大小大于8000字节。这就是我需要使用varbinary(max)
类型的原因。
但sp_oamethod读取返回错误。
有人知道使用sp_oamethod解决我的问题很热吗?
declare @returnCode int
declare @v_file int
declare @v_buffer varbinary(max)
declare @v_fullpath nvarchar(400) --pdf file phusical location
exec @returncode = sp_oacreate 'adodb.stream', @v_file out
exec @returncode = sp_oamethod @v_file, 'open'
exec @returncode = sp_oasetproperty @v_file, 'type', 1
exec @returncode = sp_oasetproperty @v_file, 'loadfromfile', @v_fullpath
exec @returnCode = sp_oamethod @v_file, 'read', @v_buffer out, -1
if @returncode <> 0
begin
exec sp_oageterrorinfo @v_file
end
exec @returnCode = sp_OAMethod @v_file, 'Close'
exec @returnCode = sp_OADestroy @v_file
sp_oageterrorinfo
返回的错误消息:
0x8004271A,ODSOLE扩展过程,srv_convert中的错误。
答案 0 :(得分:2)
请不要使用OLE自动化存储过程(即sp_OA*
),因为自SQL Server 2005发布以来,它们已被弃用。使用SQLCLR(即SQL Server中存在的基于.NET的对象),您要做的事情相当简单。您可以创建标量函数来接受文件路径并使用File.ReadAllBytes方法返回其字节。通过byte[]
类型返回SqlBytes
。
您需要将程序集设置为PERMISSION_SET = EXTERNAL_ACCESS
。为了实现这一点,请不将数据库设置为TRUSTWORTHY ON
,因为这是一个不必要的安全风险。而是,签署程序集(使用密码),然后在DLL中的master
数据库中创建一个非对称密钥,然后从该密钥创建一个登录,最后授予登录EXTERNAL ACCESS ASSEMBLY
权限。 / p>
有关使用SQLCLR的更多信息,包括许多示例,请参阅我在SQL Server Central上撰写的关于此主题的系列文章:Stairway to SQLCLR(该网站确实需要免费注册才能阅读他们的内容)。
或者,如果您不想处理任何编码,我创建了一个包含270多个函数和存储过程的库,名为SQL#。有几个与文件系统相关的功能,但免费版本中没有一个可用。仍然,这里有帮助的是: File_GetFileBinary 。
答案 1 :(得分:0)
如果尝试将大于4000个字符但长度小于或等于8000个字符的字符串传递给sp_OASetProperty或sp_OAMethod OLE自动化扩展存储过程,则输入字符串将在其之前以无提示方式截断为4000个字符被传递给对象,不会返回任何错误。
如果尝试通过sp_OASetProperty OLE自动化扩展存储过程将属性设置为大于8000个字符的字符串,或者尝试将输入参数传递给长度超过8000的sp_OAMethod OLE自动化扩展存储过程字符,您收到以下错误信息:
Console.ReadLine();
答案 2 :(得分:0)
如果有人有同样的问题,我这样做了:
在我的程序中,我创建了临时#IMG
表:
create table #IMG (FileID2 nvarchar(50), img image)
如果文件大小超过8k,我将其拆分为大小为8000的部分并更新#IMG:
exec @returnCode = sp_oamethod @v_file, 'read', @v_buffer out, 8000
update #IMG set img = @v_buffer
SELECT @ptrval = TEXTPTR(Img) FROM #IMG WHERE FileID2 = @v_FileID2
--file split section
select @v_Blocks = @v_FileSize/8000+1
if @v_Blocks = 1
begin
WRITETEXT #IMG.Img @ptrval @v_buffer
end
else
begin
WRITETEXT #IMG.Img @ptrval @v_buffer
set @j=@v_blocks-1
while @j>0
begin
exec @returnCode = sp_oamethod @v_file, 'read', @v_buffer out , 8000
set @i=(select DATALENGTH(Img) from #IMG WHERE FileID2= @v_FileID2)
UPDATETEXT #IMG.Img @ptrval @i 0 @v_buffer
set @j=@j-1
end
end
答案 3 :(得分:0)
您可以使用与0x8004271A ODSOLE Extended Procedure Error in srv_convert.
中所述相同的解决方法在你的情况下,行
exec @returnCode = sp_oamethod @v_file, 'read', @v_buffer out, -1
应替换为
Create table #tmp(dt varbinary(max))
insert into #tmp
exec @hr = sp_oamethod @v_file, 'read', @mode = -1
Select dt from #tmp -- single column/single row.
Drop Table #tmp -- clean up
警告:此代码未经过测试。但是,以下代码适用于32KB xml输出:
Create table #tmp(dt xml)
insert into #tmp
exec @hr = sp_OAGetProperty @obj, 'responseXML.XML'
/*
Here is the trick: inserting from the returned result set, i.e.
`insert into <table>(<columns>) select <columns>`
*/
Select dt from #tmp -- single column/single row.
Drop Table #tmp -- clean up
调用responseXML.XML
后, MSXML2.ServerXMLHttp.send
返回整个xml文档。该技巧根据sp_OAMethod的Result Sets
部分工作。
当table
变量类型可用时,代码可以更短:
DECLARE @xml(val xml);
insert into @xml
exec @hr = sp_OAGetProperty @obj, 'responseXML.XML'
Select * from @xml; -- just to see the output
即。没有必要清理。