社区
ASP
帖子详情
搞分寻找ASP+oracle高手!如何实现客户端的图片存到数据库中的BLOB字段中?
lhjiang
2002-12-27 10:18:10
搞分寻找ASP+oracle高手!如何实现客户端的图片存到远程数据库oracle中的BLOB字段中?
...全文
55
10
打赏
收藏
搞分寻找ASP+oracle高手!如何实现客户端的图片存到数据库中的BLOB字段中?
搞分寻找ASP+oracle高手!如何实现客户端的图片存到远程数据库oracle中的BLOB字段中?
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
10 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
hchxxzx
2003-01-10
打赏
举报
回复
http://www.newhua.com/LyfUpload.htm
lhjiang
2003-01-10
打赏
举报
回复
哦,谢谢
那个上传组件呢,给我一个吧,我试试看!
hchxxzx
2003-01-09
打赏
举报
回复
给你一个我现在用的
'创建数据链接
Set OraSession=CreateObject("OracleInProcServer.XOraSession")
Set cn=OraSession.DbOpenDatabase("autop","system/manager",0)
'取得blob表的新ID,假设此此处是更新记录
blob_id=xxx
Set obj = Server.CreateObject("LyfUpload.UploadFile") '用刘玉锋上传组件上传lyfupload
blb_filename=obj.SaveFiletodb("src") '保存文件到服务器
blb_mimetype=obj.filetype("src")'得到文件类型
'初始化原表的BLOB字段,用empty_blob()的方式,一定要,当然更新的时候如果能够确认原先已有值可不必进行此操作
'如果是插入数值,必须
'cn.executesql("insert into asm_blob(blob_id,blb_content) value('"&blob_id&"',empty_blob()")
sql0="update asm_blob set blb_content=empty_blob() where blb_id='"&blob_id&"'"
cn.executesql(sql0)
'取出该记录
strsql="select blb_content from asm_blob where blb_id='"&blob_id&"'"
Set rs0 = cn.CreateDynaset(strsql,0)
set infoblob=rs0.fields("blb_content").value
chunk=obj.dbcontent '此处obj.dbcontent是lyfupload的二进制取值方式
chunksize=lenb(chunk)
rs0.edit '打开
infoblob.offset=1 '锁定
amount_written=infoblob.write(chunk,chunksize) '写入
rs0.Update '更新
rs0.close
Set infoblob = nothing
set cn.close
set cn=nothing
gucs
2003-01-08
打赏
举报
回复
去搜索一下,有很多这样的文字。
就像上面朋友回答的,哪一种数据库都无所谓,主要是,你懂得了道理。
lhjiang
2003-01-08
打赏
举报
回复
我已经把所有的 贴子都找遍了,但是程序还是没有成功阿,或者告诉我哪里要注意的地方。另外有没有什么正确的代码,给我发一个阿
lhj827@eyou.com 马上送分
lhjiang
2002-12-30
打赏
举报
回复
你的意思说肯定是先上传到服务器端,然后再插入的??那如果我上传以后,在服务器端怎么控制插入?
ahalf
2002-12-30
打赏
举报
回复
当然要上传的服务端
lhjiang
2002-12-30
打赏
举报
回复
帮我澄清一下概念,如果客户端把图片存入远程的Oracle数据库中的BLOB字段,那么它是先要上传再插入数据库中的,还是直接可以在客户端做插入的?
_TMG_
2002-12-28
打赏
举报
回复
哪一种数据库都是同一个道理, 使用 GetChunk 就应该可以了
逍遥小贼
2002-12-27
打赏
举报
回复
以下是一位高手的回答,也许对你有帮助:
1. use ADO GetChunk method
HOWTO: Read and Write BLOBs Using GetChunk and AppendChunk
http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q194975&
2. use oo4o objects
Oracle大文本在ASP中存取问题的解决
http://www.soho-works.com/documents/asp/94.htm
论文研究-16基于
ASP
和
Oracle
的网络
图片
数据库
的设计与
实现
.pdf
网络
图片
数据库
系统采用B/S体系结构,利用Windows 2000 Server的IIS 5.0及Linux平台下
Oracle
8i构建,使用了专门组件来
实现
缩略图的自动生成,利用ADO的Stream对象快捷地在
Oracle
的Long Raw与
Blob
两种大二进制
字段
中
存储
图片
数据,保证了所有存储内容物理上的一体性。在开发了各种常规
数据库
管理功能的基础上,进行了“
图片
专题”等功能开发,为扩展
图片
数据库
的应用模式进行了新尝试。
ssh(structs,spring,hibernate)框架
中
的上传下载
Struts+Spring+Hibernate
实现
上传下载 本文将围绕SSH文件上传下载的主题,向您详细讲述如何开发基于SSH的Web程序。SSH各框架的均为当前最新版本: •Struts 1.2 •Spring 1.2.5 •Hibernate 3.0 本文选用的
数据库
为
Oracle
9i,当然你可以在不改动代码的情况下,通过配置文件的调整将其移植到任何具有
Blob
字段
类型的
数据库
上,如MySQL,SQLServer等。 总体
实现
上传文件保
存到
T_FILE表
中
,T_FILE表结构如下: 图 1 T_FILE表结构 其
中
: •FILE_ID:文件ID,32个字符,用Hibernate的uuid.hex算法生成。 •FILE_NAME:文件名。 •FILE_CONTENT:文件内容,对应
Oracle
的
Blob
类型。 •REMARK:文件备注。 文件数据存储在
Blob
类型的FILE_CONTENT表
字段
上,在Spring
中
采用
Oracle
LobHandler来处理Lob
字段
(包括Clob和
Blob
),由于在程序
中
不需要引用到
oracle
数据驱动程序的具体类且屏蔽了不同
数据库
处理Lob
字段
方法上的差别,从而撤除程序在多
数据库
移植上的樊篱。 1.首先数据表
中
的
Blob
字段
在Java领域对象
中
声明为byte[]类型,而非java.sql.
Blob
类型。 2.数据表
Blob
字段
在Hibernate持久化映射文件
中
的type为org.springframework.orm.hibernate3.support.
Blob
ByteArrayType,即Spring所提供的用户自定义的类型,而非java.sql.
Blob
。 3在Spring
中
使用org.springframework.jdbc.support.lob.
Oracle
LobHandler处理
Oracle
数据库
的
Blob
类型
字段
。 通过这样的设置和配置,我们就可以象持久化表的一般
字段
类型一样处理
Blob
字段
了。 以上是Spring+Hibernate将文件二进制数据持久化到
数据库
的解决方案,而Struts通过将表单
中
file类型的组件映射为ActionForm
中
类型为org.apache.struts.upload. FormFile的属性来获取表单提交的文件数据。 工程的类按SSH的层次结构划分为数据持久层、业务层和Web层;WEB-INF下的applicationContext.xml为Spring的配置文件,struts-config.xml为Struts的配置文件,file-upload.jsp为文件上传页面,file-list.jsp为文件列表页面。 本文后面的章节将从数据持久层->业务层->Web层的开发顺序,逐层讲解文件上传下载的开发过程。 数据持久层 1、领域对象及映射文件 您可以使用Hibernate Middlegen、HIbernate Tools、Hibernate Syhchronizer等工具或手工的方式,编写Hibernate的领域对象和映射文件。其
中
对应T_FILE表的领域对象Tfile.java为: 代码 1 领域对象Tfile 1. package sshfile.model; 2. public class Tfile 3.{ 4. private String fileId; 5. private String fileName; 6. private byte[] fileContent; 7. private String remark; 8. …//getter and setter 9. } 特别需要注意的是:
数据库
表为
Blob
类型的
字段
在Tfile
中
的fileContent类型为byte[]。Tfile的Hibernate映射文件Tfile.hbm.xml放在Tfile .java类文件的相同目录下: 代码 2 领域对象映射文件 1. <?xml version="1.0"?> 2. <!DOCTYPE hibernate-mapping PUBLIC 3. "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > 5. <hibernate-mapping> 6. <class name="sshfile.model.Tfile" table="T_FILE"> 7. <id name="fileId" type="java.lang.String" column="FILE_ID"> 8. <generator class="uuid.hex"/> 9. </id> 10. <property name="fileContent" 11. type="org.springframework.orm.hibernate3.support.
Blob
ByteArrayType" 12. column="FILE_CONTENT" lazy="true"/> 13. …//其它一般
字段
的映射 14. </class> 15. </hibernate-mapping> fileContent
字段
映射为Spring所提供的
Blob
ByteArrayType类型,
Blob
ByteArrayType是用户自定义的数据类型,它
实现
了Hibernate 的org.hibernate.usertype.UserType接口。
Blob
ByteArrayType使用从sessionFactory获取的Lob操作句柄lobHandler将byte[]的数据保
存到
Blob
数据库
字段
中
。这样,我们就再没有必要通过硬编码的方式,先insert然后再update来完成
Blob
类型数据的持久化,这个原来难伺候的老爷终于被平民化了。关于lobHandler的配置请见本文后面的内容。 此外lazy="true"说明地返回整个Tfile对象时,并不返回fileContent这个
字段
的数据,只有在显式调用tfile.getFileContent()方法时才真正从
数据库
中
获取fileContent的数据。这是Hibernate3引入的新特性,对于包含重量级大数据的表
字段
,这种抽取方式提高了对大
字段
操作的灵活性,否则加载Tfile对象的结果集时如果总是返回fileContent,这种批量的数据抽取将可以引起
数据库
的"洪泛效应"。 2、DAO编写和配置 Spring强调面向接口编程,所以我们将所有对Tfile的数据操作的方法定义在TfileDAO接口
中
,这些接口方法分别是: •findByFildId(String fileId) •save(Tfile tfile) •List findAll() TfileDAOHibernate提供了对TfileDAO接口基于Hibernate的
实现
,如代码 3所示: 代码 3 基于Hibernate 的fileDAO
实现
类 1. package sshfile.dao; 2. 3. import sshfile.model.*; 4. import org.springframework.orm.hibernate3.support.HibernateDaoSupport; 5. import java.util.List; 6. 7. public class TfileDAOHibernate 8. extends HibernateDaoSupport implements TfileDAO 9. { 10. public Tfile findByFildId(String fileId) 11. { 12. return (Tfile) getHibernateTemplate().get(Tfile.class, fileId); 13. } 14. public void save(Tfile tfile) 15. { 16. getHibernateTemplate().save(tfile); 17. getHibernateTemplate().flush(); 18. } 19. public List findAll() 20. { 21. return getHibernateTemplate().loadAll(Tfile.class); 22. } 23. } TfileDAOHibernate通过扩展Spring提供的Hibernate支持类HibernateDaoSupport而建立,HibernateDaoSupport封装了HibernateTemplate,而HibernateTemplate封装了Hibernate所提供几乎所有的的数据操作方法,如execute(HibernateCallback action),load(Class entityClass, Serializable id),save(final Object entity)等等。 所以我们的DAO只需要简单地调用父类的HibernateTemplate就可以完成几乎所有的
数据库
操作了。 由于Spring通过代理Hibernate完成数据层的操作,所以原Hibernate的配置文件hibernate.cfg.xml的信息也转移到Spring的配置文件
中
: 代码 4 Spring
中
有关Hibernate的配置信息 1. <beans> 2. <!-- 数据源的配置 //--> 3. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 4. destroy-method="close"> 5. <property name="driverClassName" value="
oracle
.jdbc.driver.
Oracle
Driver"/> 6. <property name="url" value="jdbc:
oracle
:thin:@localhost:1521:ora9i"/> 7. <property name="username" value="test"/> 8. <property name="password" value="test"/> 9. </bean> 10. <!-- Hibernate会话工厂配置 //--> 11. <bean id="sessionFactory" 12. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 13. <property name="dataSource" ref="dataSource"/> 14. <property name="mappingDirectoryLocations"> 15. <list> 16. <value>classpath:/sshfile/model</value> 17. </list> 18. </property> 19. <property name="hibernateProperties"> 20. <props> 21. <prop key="hibernate.dialect">org.hibernate.dialect.
Oracle
Dialect</prop> 22. <prop key="hibernate.cglib.use_reflection_optimizer">true</prop> 23. </props> 24. </property> 25. </bean> 26. <!-- Hibernate 模板//--> 27. <bean id="hibernateTemplate" 28. class="org.springframework.orm.hibernate3.HibernateTemplate"> 29. <property name="sessionFactory" ref="sessionFactory"/> 30. </bean> 31. <!--DAO配置 //--> 32. <bean id="tfileDAO" class="sshfile.dao.TfileDAOHibernate"> 33. <property name="hibernateTemplate" ref="hibernateTemplate" /> 34. </bean> 35. … 36. </beans> 第3~9行定义了一个数据源,其
实现
类是apache的BasicDataSource,第11~25行定义了Hibernate的会话工厂,会话工厂类用Spring提供的LocalSessionFactoryBean维护,它注入了数据源和资源映射文件,此外还通过一些键值对设置了Hibernate所需的属性。 其
中
第16行通过类路径的映射方式,将sshfile.model类包目录下的所有领域对象的映射文件装载进来,在本文的例子里,它将装载进Tfile.hbm.xml映射文件。如果有多个映射文件需要声明,使用类路径映射方式显然比直接单独指定映射文件名的方式要简便。 第27~30行定义了Spring代理Hibernate数据操作的HibernateTemplate模板,而第32~34行将该模板注入到tfileDAO
中
。 需要指定的是Spring 1.2.5提供了两套Hibernate的支持包,其
中
Hibernate 2相关的封装类位于org.springframework.orm.hibernate2.*包
中
,而Hibernate 3.0的封装类位于org.springframework.orm.hibernate3.*包
中
,需要根据您所选用Hibernate版本进行正确选择。 3、Lob
字段
处理的配置 我们前面已经指出
Oracle
的Lob
字段
和一般类型的
字段
在操作上有一个明显的区别--那就是你必须首先通过
Oracle
的empty_
blob
()/empty_clob()初始化Lob
字段
,然后获取该
字段
的引用,通过这个引用更改其值。所以要完成对Lob
字段
的操作,Hibernate必须执行两步
数据库
访问操作,先Insert再Update。 使用
Blob
ByteArrayType
字段
类型后,为什么我们就可以象一般的
字段
类型一样操作
Blob
字段
呢?可以确定的一点是:
Blob
ByteArrayType不可能逾越
Blob
天生的操作方式,原来是
Blob
ByteArrayType数据类型本身具体数据访问的功能,它通过LobHandler将两次数据访问的动作隐藏起来,使
Blob
字段
的操作在表现上和其他一般
字段
业类型无异,所以LobHandler即是那个"苦了我一个,幸福十亿人"的那位幕后英雄。 LobHandler必须注入到Hibernate会话工厂sessionFactory
中
,因为sessionFactory负责产生与
数据库
交互的Session。LobHandler的配置如代码 5所示: 代码 5 Lob
字段
的处理句柄配置 1. <beans> 2. … 3. <bean id="nativeJdbcExtractor" 4. class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor" 5. lazy-init="true"/> 6. <bean id="lobHandler" 7. class="org.springframework.jdbc.support.lob.
Oracle
LobHandler" lazy-init="true"> 8. <property name="nativeJdbcExtractor"> 9. <ref local="nativeJdbcExtractor"/> 10. </property> 11. </bean> 12. … 13. </beans> 首先,必须定义一个能够从连接池
中
抽取出本地
数据库
JDBC对象(如
Oracle
Connection,
Oracle
ResultSet等)的抽取器:nativeJdbcExtractor,这样才可以执行一些特定
数据库
的操作。对于那些仅封装了Connection而未包括Statement的简单数据连接池,SimpleNativeJdbcExtractor是效率最高的抽取器
实现
类,但具体到apache的BasicDataSource连接池,它封装了所有JDBC的对象,这时就需要使用CommonsDbcpNativeJdbcExtractor了。Spring针对几个著名的Web服务器的数据源提供了相应的JDBC抽取器: •WebLogic:WebLogicNativeJdbcExtractor •WebSphere:WebSphereNativeJdbcExtractor •JBoss:JBossNativeJdbcExtractor 在定义了JDBC抽取器后,再定义lobHandler。Spring 1.2.5提供了两个lobHandler: •DefaultLobHandler:适用于大部分的
数据库
,如SqlServer,MySQL,对
Oracle
10g也适用,但不适用于
Oracle
9i(看来
Oracle
9i确实是个怪胎,谁叫
Oracle
公司自己都说
Oracle
9i是一个过渡性的产品呢)。 •
Oracle
LobHandler:适用于
Oracle
9i和
Oracle
10g。 由于我们的
数据库
是
Oracle
9i,所以使用
Oracle
LobHandler。 在配置完LobHandler后, 还需要将其注入到sessionFactory的Bean
中
,下面是调用后的sessionFactory Bean的配置: 代码 6 将lobHandler注入到sessionFactory
中
的配置 1. <beans> 2. … 3. <bean id="sessionFactory" 4. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 5. <property name="dataSource" ref="dataSource"/> 6. <!-- 为处理
Blob
类型
字段
的句柄声明 //--> 7. <property name="lobHandler" ref="lobHandler"/> 8. … 9. </bean> 10. … 11. </beans> 如第7所示,通过sessionFactory的lobHandler属性进行注入。 业务层 1、业务层接口 "面向接口而非面向类编程"是Spring不遗余力所推荐的编程原则,这条原则也已经为大部开发者所接受;此外,JDK的动态代理只对接口有效,否则必须使用CGLIB生成目标类的子类。我们依从于Spring的倡导为业务类定义一个接口: 代码 7 业务层操作接口 1. public interface FileService 2. { 3. void save(FileActionForm fileForm);//将提交的上传文件保
存到
数据表
中
4. List getAllFile();//得到T_FILE所示记录 5. void write(OutputStream os,String fileId);//将某个文件的文件数据写出到输出流
中
6. String getFileName(String fileId);//获取文件名 7. } 其
中
save(FileActionForm fileForm)方法,将封装在fileForm
中
的上传文件保
存到
数据库
中
,这里我们使用FileActionForm作为方法入参,FileActionForm是Web层的表单数据对象,它封装了提交表单的数据。将FileActionForm直接作为业务层的接口入参,相当于将Web层传播到业务层
中
去,即将业务层绑定在特定的Web层
实现
技术
中
,按照分层模型学院派的观点,这是一种反模块化的设计,但在"一般"的业务系统并无需提供多种UI界面,系统Web层将来切换到另一种
实现
技术的可能性也微乎其微,所以笔者觉得没有必要为了这个业务层完全独立于调用层的过高目标而去搞一个额外的隔离层,浪费了原材料不说,还将系统搞得过于复杂,相比于其它原则,"简单"始终是最大的一条原则。 getAllFile()负责获取T_FILE表所有记录,以便在网页上显示出来。 而getFileName(String fileId)和write(OutputStream os,String fileId)则用于下载某个特定的文件。具体的调用是将Web层将response.getOutputStream()传给write(OutputStream os,String fileId)接口,业务层直接将文件数据输出到这个响应流
中
。具体
实现
请参见错误!未找到引用源。节下载文件部分。 2、业务层接口
实现
类 FileService的
实现
类为FileServiceImpl,其
中
save(FileActionForm fileForm)的
实现
如下所示: 代码 8 业务接口
实现
类之save() 1. … 2. public class FileServiceImpl 3. implements FileService 4. { 5. private TfileDAO tfileDAO; 6. public void save(FileActionForm fileForm) 7. { 8. Tfile tfile = new Tfile(); 9. try 10. { 11. tfile.setFileContent(fileForm.getFileContent().getFileData()); 12. } 13. catch (FileNotFoundException ex) 14. { 15. throw new RuntimeException(ex); 16. } 17. catch (IOException ex) 18. { 19. throw new RuntimeException(ex); 20. } 21. tfile.setFileName(fileForm.getFileContent().getFileName()); 22. tfile.setRemark(fileForm.getRemark()); 23. tfileDAO.save(tfile); 24. } 25. … 26. } 在save(FileActionForm fileForm)方法里,完成两个步骤: 其一,象在水桶间倒水一样,将FileActionForm对象
中
的数据倒入到Tfile对象
中
; 其二,调用TfileDAO保存数据。 需要特别注意的是代码的第11行,FileActionForm的fileContent属性为org.apache.struts.upload.FormFile类型,FormFile提供了一个方便的方法getFileData(),即可获取文件的二进制数据。通过解读FormFile接口
实现
类DiskFile的原码,我们可能知道FormFile本身并不缓存文件的数据,只有实际调用getFileData()时,才从磁盘文件输入流
中
获取数据。由于FormFile使用流读取方式获取数据,本身没有缓存文件的所有数据,所以对于上传超大体积的文件,也是没有问题的;但是,由于数据持久层的Tfile使用byte[]来缓存文件的数据,所以并不适合处理超大体积的文件(如100M),对于超大体积的文件,依然需要使用java.sql.
Blob
类型以常规流操作的方式来处理。 此外,通过FileForm的getFileName()方法就可以获得上传文件的文件名,如第21行代码所示。 write(OutputStream os,String fileId)方法的
实现
,如代码 9所示: 代码 9 业务接口
实现
类之write() 1. … 2. public class FileServiceImpl 3. implements FileService 4. { 5. 6. public void write(OutputStream os, String fileId) 7. { 8. Tfile tfile = tfileDAO.findByFildId(fileId); 9. try 10. { 11. os.write(tfile.getFileContent()); 12. os.flush(); 13. } 14. catch (IOException ex) 15. { 16. throw new RuntimeException(ex); 17. } 18. } 19. … 20. } write(OutputStream os,String fileId)也简单地分为两个操作步骤,首先,根据fileId加载表记录,然后将fileContent写入到输出流
中
。 3、Spring事务配置 下面,我们来看如何在Spring配置文件
中
为FileService配置声明性的事务 1. <beans> 2. … 3. <bean id="transactionManager" 4. class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 5. <property name="sessionFactory" ref="sessionFactory"/> 6. </bean> 7. <!-- 事务处理的AOP配置 //--> 8. <bean id="txProxyTemplate" abstract="true" 9. class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> 10. <property name="transactionManager" ref="transactionManager"/> 11. <property name="transactionAttributes"> 12. <props> 13. <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> 14. <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> 15. <prop key="save">PROPAGATION_REQUIRED</prop> 16. <prop key="write">PROPAGATION_REQUIRED,readOnly</prop> 17. </props> 18. </property> 19. </bean> 20. <bean id="fileService" parent="txProxyTemplate"> 21. <property name="target"> 22. <bean class="sshfile.service.FileServiceImpl"> 23. <property name="tfileDAO" ref="tfileDAO"/> 24. </bean> 25. </property> 26. </bean> 27. </beans> Spring的事务配置包括两个部分: 其一,定义事务管理器transactionManager,使用HibernateTransactionManager
实现
事务管理; 其二,对各个业务接口进行定义,其实txProxyTemplate和fileService是父子节点的关系,本来可以将txProxyTemplate定义的内容合并到fileService
中
一起定义,由于我们的系统仅有一个业务接口需要定义,所以将其定义的一部分抽象到父节点txProxyTemplate
中
意义确实不大,但是对于真实的系统,往往拥有为数众多的业务接口需要定义,将这些业务接口定义内容的共同部分抽取到一个父节点
中
,然后在子节点
中
通过parent进行关联,就可以大大简化业务接口的配置了。 父节点txProxyTemplate注入了事务管理器,此外还定义了业务接口事务管理的方法(允许通过通配符的方式进行匹配声明,如前两个接口方法),有些接口方法仅对数据进行读操作,而另一些接口方法需要涉及到数据的更改。对于前者,可以通过readOnly标识出来,这样有利于操作性能的提高,需要注意的是由于父类节点定义的Bean仅是子节点配置信息的抽象,并不能具体
实现
化一个Bean对象,所以需要特别标注为abstract="true",如第8行所示。 fileService作为一个目标类被注入到事务代理器
中
,而fileService
实现
类所需要的tfileDAO实例,通过引用3.2节
中
定义的tfileDAO Bean注入。 Web层
实现
1、Web层的构件和交互流程 Web层包括主要3个功能: •上传文件。 •列出所有已经上传的文件列表,以供点击下载。 •下载文件。 Web层
实现
构件包括与2个JSP页面,1个ActionForm及一个Action: •file-upload.jsp:上传文件的页面。 •file-list.jsp:已经上传文件的列表页面。 •FileActionForm:file-upload.jsp页面表单对应的ActionForm。 •FileAction:继承org.apache.struts.actions.DispatchAction的Action,这样这个Action就可以通过一个URL参数区分
中
响应不同的请求。 Web层的这些构件的交互流程如图 6所示: 图 6 Web层Struts流程图 其
中
,在执行文件上传的请求时,FileAction在执行文件上传后,forward到loadAllFile出口
中
,loadAllFile加载
数据库
中
所有已经上传的记录,然后forward到名为fileListPage的出口
中
,调用file-list.jsp页面显示已经上传的记录。 2、FileAction功能 Struts 1.0的Action有一个弱项:一个Action只能处理一种请求,Struts 1.1
中
引入了一个DispatchAction,允许通过URL参数指定调用Action
中
的某个方法,如http://yourwebsite/fileAction.do?method=upload即调用FileAction
中
的upload方法。通过这种方式,我们就可以将一些相关的请求集
中
到一个Action当
中
编写,而没有必要为某个请求操作编写一个Action类。但是参数名是要在struts-config.xml
中
配置的: 1. <struts-config> 2. <form-beans> 3. <form-bean name="fileActionForm" type="sshfile.web.FileActionForm" /> 4. </form-beans> 5. <action-mappings> 6. <action name="fileActionForm" parameter="method" path="/fileAction" 7. type="sshfile.web.FileAction"> 8. <forward name="fileListPage" path="/file-list.jsp" /> 9. <forward name="loadAllFile" path="/fileAction.do?method=listAllFile" /> 10. </action> 11. </action-mappings> 12. </struts-config> 第6行的parameter="method"指定了承载方法名的参数,第9行
中
,我们还配置了一个调用FileAction不同方法的Action出口。 FileAction共有3个请求响应的方法,它们分别是: •upload(…):处理上传文件的请求。 •listAllFile(…):处理加载
数据库
表
中
所有记录的请求。 •download(…):处理下载文件的请求。 下面我们分别对这3个请求处理方法进行讲解。 2.1 上传文件 上传文件的请求处理方法非常简单,简之言之,就是从Spring容器
中
获取业务层处理类FileService,调用其save(FileActionForm form)方法上传文件,如下所示: 1. public class FileAction 2. extends DispatchAction 3. { 4. //将上传文件保
存到
数据库
中
5. public ActionForward upload(ActionMapping mapping, ActionForm form, 6. HttpServletRequest request, 7. HttpServletResponse response) 8. { 9. FileActionForm fileForm = (FileActionForm) form; 10. FileService fileService = getFileService(); 11. fileService.save(fileForm); 12. return mapping.findForward("loadAllFile"); 13. } 14. //从Spring容器
中
获取FileService对象 15. private FileService getFileService() 16. { 17. ApplicationContext appContext = WebApplicationContextUtils. 18. getWebApplicationContext(this.getServlet().getServletContext()); 19. return (FileService) appContext.getBean("fileService"); 20. } 21. … 22. } 由于FileAction其它两个请求处理方法也需要从Spring容器
中
获取FileService实例,所以我们特别提供了一个getFileService()方法(第15~21行)。重构的一条原则就是:"发现代码
中
有重复的表达式,将其提取为一个变量;发现类
中
有重复的代码段,将其提取为一个方法;发现不同类
中
有相同的方法,将其提取为一个类"。在真实的系统
中
,往往拥有多个Action和多个Service类,这时一个比较好的设置思路是,提供一个获取所有Service
实现
对象的工具类,这样就可以将Spring 的Service配置信息屏蔽在一个类
中
,否则Service的配置名字散落在程序各处,维护性是很差的。 2.2 列出所有已经上传的文件 listAllFile方法调用Servie层方法加载T_FILE表
中
所有记录,并将其保存在Request域
中
,然后forward到列表页面
中
: 1. public class FileAction 2. extends DispatchAction 3. { 4. … 5. public ActionForward listAllFile(ActionMapping mapping, ActionForm form, 6. HttpServletRequest request, 7. HttpServletResponse response) 8. throws ModuleException 9. { 10. FileService fileService = getFileService(); 11. List fileList = fileService.getAllFile(); 12. request.setAttribute("fileList",fileList); 13. return mapping.findForward("fileListPage"); 14. } 15. } file-list.jsp页面使用Struts标签展示出保存在Request域
中
的记录: 1. <%@page contentType="text/html; charset=GBK"%> 2. <%@taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%> 3. <%@taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%> 4. <html> 5. <head> 6. <title>file-download</title> 7. </head> 8. <body bgcolor="#ffffff"> 9. <ol> 10. <logic:iterate id="item" name="fileList" scope="request"> 11. <li> 12. <a href='fileAction.do?method=download&fileId= 13. <bean:write name="item"property="fileId"/>'> 14. <bean:write name="item" property="fileName"/> 15. </a> 16. </li> 17. </logic:iterate> 18. </ol> 19. </body> 20. </html> 展现页面的每条记录挂接着一个链接地址,形如:fileAction.do?method=download&fileId=xxx,method参数指定了这个请求由FileAction的download方法来响应,fileId指定了记录的主键。 由于在FileActionForm
中
,我们定义了fileId的属性,所以在download响应方法
中
,我们将可以从FileActionForm
中
取得fileId的值。这里涉及到一个处理多个请求Action所对应的ActionForm的设计问题,由于原来的Action只能对应一个请求,那么原来的ActionForm非常简单,它仅需要将这个请求的参数项作为其属性就可以了,但现在一个Action对应多个请求,每个请求所对应的参数项是不一样的,此时的ActionForm的属性就必须是多请求参数项的并集了。所以,除了文件上传请求所对应的fileContent和remark属性外还包括文件下载的fileId属性: 图 7 FileActionForm 当然这样会造成属性的冗余,比如在文件上传的请求
中
,只会用到fileContent和remark属性,而在文件下载的请求时,只会使用到fileId属性。但这种冗余是会带来好处的--它使得一个Action可以处理多个请求。 2.3 下载文件 在列表页面
中
点击一个文件下载,其请求由FileAction的download方法来响应,download方法调用业务层的FileService方法,获取文件数据并写出到response的响应流
中
。通过合理设置HTTP响应头参数,将响应流在
客户端
表现为一个下载文件对话框,其代码如下所示: 代码 10 业务接口
实现
类之download 1. public class FileAction 2. extends DispatchAction 3. { 4. … 5. public ActionForward download(ActionMapping mapping, ActionForm form, 6. HttpServletRequest request, 7. HttpServletResponse response) 8. throws ModuleException 9. { 10. FileActionForm fileForm = (FileActionForm) form; 11. FileService fileService = getFileService(); 12. String fileName = fileService.getFileName(fileForm.getFileId()); 13. try 14. { 15. response.setContentType("application/x-msdownload"); 16. response.setHeader("Content-Disposition", 17. "attachment;" + " filename="+ 18. new String(fileName.getBytes(), "ISO-8859-1")); 19. fileService.write(response.getOutputStream(), fileForm.getFileId()); 20. } 21. catch (Exception e) 22. { 23. throw new ModuleException(e.getMessage()); 24. } 25. return null; 26. } 27. } 第15~18行,设置HTTP响应头,将响应类型设置为application/x-msdownload MIME类型,则响应流在IE
中
将弹出一个文件下载的对话框,如图 4所示。IE所支持的MIME类型多达26种,您可以通过这个网址查看其他的MIME类型: http://msdn.microsoft.com/workshop/networking/moniker/overview/appendix_a.
asp
。 如果下载文件的文件名含有
中
文字符,如果不对其进行硬编码,如第18行所示,客户文件下载对话框
中
出现的文件名将会发生乱码。 第19行代码获得response的输出流,作为FileServie write(OutputStream os,String fileId)的入参,这样文件的内容将写到response的输出流
中
。 3、web.xml文件的配置 Spring容器在何时启动呢?我可以在Web容器初始化来执行启动Spring容器的操作,Spring提供了两种方式启动的方法: •通过org.springframework.web.context .ContextLoaderListener容器监听器,在Web容器初始化时触发初始化Spring容器,在web.xml
中
通过<listener></listener>对其进行配置。 •通过Servlet org.springframework.web.context.ContextLoaderServlet,将其配置为自动启动的Servlet,在Web容器初始化时,通过这个Servlet启动Spring容器。 在初始化Spring容器之前,必须先初始化log4J的引擎,Spring也提供了容器监听器和自动启动Servlet两种方式对log4J引擎进行初始化: •org.springframework.web.util .Log4jConfigListener •org.springframework.web.util.Log4jConfigServlet 下面我们来说明如何配置web.xml启动Spring容器: 代码 11 web.xml
中
对应Spring的配置内容 1. <web-app> 2. <context-param> 3. <param-name>contextConfigLocation</param-name> 4. <param-value>/WEB-INF/applicationContext.xml</param-value> 5. </context-param> 6. <context-param> 7. <param-name>log4jConfigLocation</param-name> 8. <param-value>/WEB-INF/log4j.properties</param-value> 9. </context-param> 10. <servlet> 11. <servlet-name>log4jInitServlet</servlet-name> 12. <servlet-class>org.springframework.web.util.Log4jConfigServlet</servlet-class> 13. <load-on-startup>1</load-on-startup> 14. </servlet> 15. <servlet> 16. <servlet-name>springInitServlet</servlet-name> 17. <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> 18. <load-on-startup>2</load-on-startup> 19. </servlet> 20. … 21. </web-app> 启动Spring容器时,需要得到两个信息:Spring配置文件的地址和Log4J属性文件,这两上信息分别通过contextConfigLocationWeb和log4jConfigLocation容器参数指定,如果有多个Spring配置文件,则用逗号隔开,如: /WEB-INF/applicationContext_1.xml, /WEB-INF/applicationContext_1.xm2 由于在启动ContextLoaderServlet之前,必须事先初始化Log4J的引擎,所以Log4jConfigServlet必须在ContextLoaderServlet之前启动,这通过<load-on-startup>来指定它们启动的先后顺序。 乱码是开发Web应用程序一个比较老套又常见问题,由于不同Web应用服务器的默认编码是不一样的,为了方便Web应用在不同的Web应用服务器上移植,最好的做法是Web程序自身来处理编码转换的工作。经典的作法是在web.xml
中
配置一个编码转换过滤器,Spring就提供了一个编码过滤器类CharacterEncodingFilter,下面,我们为应用配置上这个过滤器: 1. <web-app> 2. … 3. <filter> 4. <filter-name>encodingFilter</filter-name> 5. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 6. <init-param> 7. <param-name>encoding</param-name> 8. <param-value>GBK</param-value> 9. </init-param> 10. </filter> 11. <filter-mapping> 12. <filter-name>encodingFilter</filter-name> 13. <url-pattern>/*</url-pattern> 14. </filter-mapping> 15. … 16. </web-app> Spring的过滤器类是org.springframework.web.filter.CharacterEncodingFilter,通过encoding参数指定编码转换类型为GBK,<filter-mapping>的配置使该过滤器截获所有的请示。 Struts的框架也需要在web.xml
中
配置,想必读者朋友对Struts的配置都很熟悉,故在此不再提及,请参见本文所提供的源码。 总结 本文通过一个文件上传下载的Web应用,讲解了如何构建基于SSH的Web应用,通过Struts和FormFile,Spring的LobHandler以及Spring为Hibernate
Blob
处理所提供的用户类
Blob
ByteArrayType ,
实现
上传和下载文件的功能仅需要廖廖数行的代码即告完成。读者只需对程序作稍许的调整,即可处理Clob
字段
: •领域对象对应Clob
字段
的属性声明为String类型; •映射文件对应Clob
字段
的属性声明为org.springframework.orm.hibernate3.support.ClobStringType类型。
新版通俗易懂的JDBC升级版教程(含配套资料)
本套视频教程共57小结,涵盖JDBC的方方面面,包括手动获取
数据库
连接的多种方式、使用
数据库
连接池获取连接、Statement与PreparedStatement的对比使用、sql注入问题讲解、
Blob
字段
的操作、高效的批量插入、DAO设计...
ASP
.net 操作
Oracle
的
Blob
字段
最近在做个项目,导师要求一定要用
Oracle
来存数据。所以有一个功能是要把
图片
等文件都
存到
Oracle
的
Blob
字段
里。上网搜了好久,没发现有哪个地方是讲得清楚的,最后还是得自己摸索出来。用的是
Asp
.net(C#),Odbc 方式连接
Oracle
。OdbcConnection conn = new OdbcConnection(m.connstring());OdbcComman
操作
Oracle
数据库
实现
上传
图片
到
Blob
类型的
字段
出现的问题
通过使用OleDb操作
Oracle
数据库
,成功
实现
图片
上传到
Blob
类型的
字段
,但有时会发生ORA-01036错误的问题,经查询是错误提示为illegal variable name/number,不知道有谁能详细解释illegal variable name/number的意思
Oracle
Data Provider for .NETHiI am using ODP.NET (
Oracle
ASP
28,390
社区成员
357,068
社区内容
发帖
与我相关
我的任务
ASP
ASP即Active Server Pages,是Microsoft公司开发的服务器端脚本环境。
复制链接
扫一扫
分享
社区描述
ASP即Active Server Pages,是Microsoft公司开发的服务器端脚本环境。
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章