这几天在做将文件保存到数据库的一个工作,因为在cloud中规定不能将文件download下来并且保存在server上。
要做的工作是:
1. 从FTP上download下来字节流并且保存到数据库
2.从数据库读出这个数据流并且显示相应的数据
步骤:
1.建立表ad_download_file,字段有fileid,filename,filedata。用BLOB存储文件
CREATE TABLE ad_download_file (
filename VARCHAR2(50) NOT NULL,
fileid INTEGER NOT NULL,
filedata BLOB NULL
)
2.因为cloud规定只能用存储过程,因此建了一个存储过程用于插入文件
CREATE OR REPLACE PROCEDURE sp_insert_file(fname IN VARCHAR,fdata out BLOB
) AS
countOfdata int;
BEGIN
select count(*) into countOfdata from ad_download_file where fname = filename;
if countOfdata = 0 then
insert into ad_download_file(fileid,filename,filedata) values(SEQ_AD_DOWNLOAD_FILE_ID.NEXTVAL,fname,empty_blob());
end if;
select filedata into fdata from ad_download_file where fname = filename FOR UPDATE;
END;
/
在存储过程中,先判断有没有相同名字的文件已经存在,如果不存在,则先插入一个空的blob到数据库。在最后查出这条数据的filedata。注意最后一条select语句后面有个“FOR UPDATE".用于锁定当前这行数据。
3.java 代码
public ArrayList doExecuteProcedure(String query, BaseVO valueObject) throws SWTException
{
ArrayList outputList = new ArrayList();
Connection con = null;
CallableStatement callTest = null;
try
{
DBQueryDetails dBQueryDetails = ApplicationDataConfig.getDaomap().lookupQueryHandler(query);
setBaseVO(valueObject);
con = initDBConnection(dBQueryDetails.getDatabaseName());
Logger.debug("connection Object =" + con);
boolean autoCommit = con.getAutoCommit();
con.setAutoCommit(false);
ArrayList<String> inputParamNamesArrayList = dBQueryDetails.getInputParamNamesArrayList();
Logger.debug("inputParamNamesArrayList =" + inputParamNamesArrayList);
if (inputParamNamesArrayList != null && inputParamNamesArrayList.size() > 0)
{
intializeArrayListInputs(inputParamNamesArrayList, con);
}
callTest = con.prepareCall("call " + dBQueryDetails.getQuery());
ArrayList<String> inputParamNames = dBQueryDetails.getInputParamNames();
ArrayList inputParamValues = intializeQueryInputs(inputParamNames);
int i = 1;
for (int j = 0; j < inputParamValues.size(); j++, i++)
{
callTest.setObject(i, inputParamValues.get(j));
}
ArrayList<String> outputParamNames = dBQueryDetails.getOutputParamNames();
Class VOClass = baseVO.getClass();
HashMap<String, String> fieldDataTypes = getFieldDataTypes(VOClass, outputParamNames);
for (int j = 0; j < outputParamNames.size(); j++, i++)
{
callTest.registerOutParameter(i, getJavaToOracleDatatype(fieldDataTypes.get(outputParamNames.get(j))));
}
callTest.execute();
//将数据通过反射设置到对象,并且返回对象链表
outputList = populateVO(i, callTest, outputParamNames, fieldDataTypes);
con.commit();
con.setAutoCommit(autoCommit);
}
catch (SQLException e)
{
Logger.error("DBAction.doExecuteProcedure() ==> " + e.getMessage(), e);
throw new SWTException(e);
}
catch (Exception e)
{
Logger.error("DBExecute.doExecuteProcedure() ==> " + e.getMessage());
throw new SWTException(e);
}
finally
{
try
{
if (callTest != null)
{
callTest.close();
callTest = null;
}
}
catch (SQLException ex)
{
Logger.error("DBAction.doExecuteProcedure() ==> " + ex.getMessage(), ex);
throw new SWTException(ex);
}
if (con != null)
{
Logger.debug("doExecuteProcedure close conn:" + con);
connMgr.freeConnection(ApplicationDataConfig.getConfiguration().getDbPoolName(), con);
}
}
return outputList;
}
//将数据通过反射设置到对象,并且返回对象链表
private ArrayList populateVO(int i, CallableStatement callTest, ArrayList<String> outputParamNames,
HashMap<String, String> fieldDataTypes) throws SWTException
{
ArrayList outputList = new ArrayList();
InputStream input = null;
OutputStream blobOutput = null;
try
{
Class VOClass = baseVO.getClass();
Object VOObject = VOClass.newInstance();
for (int j = i - outputParamNames.size(), k = 0; j < i; j++, k++)
{
String tempFieldName = outputParamNames.get(k);
String tempMethName = createMethodName(tempFieldName, "set");
Method method = VOClass.getMethod(tempMethName, Class.forName(fieldDataTypes.get(tempFieldName)));
String typeName = fieldDataTypes.get(tempFieldName);
if (DBConstants.BIGDECIMAL.equalsIgnoreCase(typeName))
{
method.invoke(VOObject, callTest.getDouble(j));
}
if (DBConstants.BOOLEAN.equalsIgnoreCase(typeName))
{
method.invoke(VOObject, callTest.getBoolean(j));
}
if (DBConstants.BYTE.equalsIgnoreCase(typeName))
{
method.invoke(VOObject, callTest.getByte(j));
}
if (DBConstants.SQL_DATE.equalsIgnoreCase(typeName))
{
method.invoke(VOObject, callTest.getDate(j));
}
if (DBConstants.UTIL_DATE.equalsIgnoreCase(typeName))
{
method.invoke(VOObject, callTest.getDate(j));
}
if (DBConstants.DOUBLE.equalsIgnoreCase(typeName))
{
method.invoke(VOObject, callTest.getDouble(j));
}
if (DBConstants.FLOAT.equalsIgnoreCase(typeName))
{
method.invoke(VOObject, callTest.getFloat(j));
}
if (DBConstants.INTEGER.equalsIgnoreCase(typeName))
{
method.invoke(VOObject, callTest.getInt(j));
}
if (DBConstants.LONG.equalsIgnoreCase(typeName))
{
method.invoke(VOObject, callTest.getLong(j));
}
if (DBConstants.OBJECT.equalsIgnoreCase(typeName))
{
method.invoke(VOObject, callTest.getObject(j));
}
if (DBConstants.SHORT.equalsIgnoreCase(typeName))
{
method.invoke(VOObject, callTest.getShort(j));
}
if (DBConstants.TIME.equalsIgnoreCase(typeName))
{
method.invoke(VOObject, callTest.getTime(j));
}
if (DBConstants.SQL_TIMESTAMP.equalsIgnoreCase(typeName))
{
method.invoke(VOObject, callTest.getTimestamp(j));
}
if (DBConstants.STRING.equalsIgnoreCase(typeName))
{
method.invoke(VOObject, callTest.getString(j));
}
if (DBConstants.BLOB.equalsIgnoreCase(typeName))
{
// When have outputStream in the object, then update to the
// database;
method.invoke(VOObject, callTest.getBlob(j));
// get the OutputStream parameter from the baseVO
String getMethName = createMethodName(tempFieldName, "get");
BLOB blob = (BLOB) callTest.getBlob(j);
if (blob != null)
{
Object obj = null;
String outputStreamName = null;
try
{
//通过反射拿到后缀名为OutputStream变量,例如
// private BLOB filedata;
// private ByteArrayOutputStream filedataOutputStream;
//filedataOutputStream用于保存数据库返回的文件数据,或者要传到数据库的文件数据
//这样做是因为文件的数据必须在connection关闭前都从数据库中拿出来。如果只返回Blob对象
//那么Blob对象中只保存了一行的数据
outputStreamName = tempFieldName + "OutputStream";
Method getOutputStreamMethod = VOClass.getMethod(createMethodName(outputStreamName, "get"));
obj = getOutputStreamMethod.invoke(baseVO);
}
catch (Exception e)
{
Logger.info("DBAction.populateVO() ==> " + e.getMessage(), e);
}
// when OutputStream is empty,need set the data into
// OutputStream object
//判断是要更新数据还是要取数据,如果OutputStream是空的表示要取数据,否则是更新数据
if (obj == null)
{
//拿到二进制数组字节流,并且写入到字节数组中
Method setOutputStreamMethod = VOClass.getMethod(createMethodName(outputStreamName, "set"), VOClass
.getDeclaredField(outputStreamName).getType());
ByteArrayOutputStream baot = new ByteArrayOutputStream();
input = blob.getBinaryStream();
int data = -1;
while ((data = input.read()) != -1)
baot.write(data);
setOutputStreamMethod.invoke(VOObject, baot);
}
// when OutputStream is not empty,update OutputStream
// object into database
//通过toByteArray()方法将数据转成字节数组
else
{
ByteArrayOutputStream baot = (ByteArrayOutputStream) obj;
blobOutput = blob.setBinaryStream(0);
blobOutput.write(baot.toByteArray());
blobOutput.flush();
}
}
}
}
outputList.add(VOObject);
}
catch (Exception e)
{
Logger.error("DBAction.populateVO() ==> " + e.getMessage(), e);
throw new SWTException(e);
}
finally
{
try
{
if (input != null)
{
input.close();
}
if (blobOutput != null)
{
blobOutput.close();
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
Logger.error("DBAction.populateVO() ==> " + e.getMessage(), e);
}
}
return outputList;
}
总结:其实这个很简单,写这篇文章的目的是记录一下怎么去做大文件存取。并总结一下要注意的地方。一共有三点
1.必须把setAutoCommit()设置成false,因为如果是true,那么select出blob对象的时候,就commit了,那么BLOB对象也就断开了和数据库的链接
2.在存文件到BLOB对象之前需要先SELECT出BLOB对象,并且用FOR UPDATA锁住这行,以便在java程序中更新
3.在connection close之前需要拿出BLOB的所有数据。
4.在文件保存的时候肯定涉及到Byte和String 之间的转换,可以用下面代码将ByteArrayOutputStream转成BufferedReader
BufferedReader in = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(readByteArrayOutputStream(fileName,
ProcessesConstants.SP_SELECT_FILE).toByteArray())));
分享到:
相关推荐
这通常包括图片读取、BASE64编码、数据库操作以及从数据库取出数据后解码还原图片的步骤。 7. **运行环境**:虽然未明确指出,但执行这个Demo可能需要一个支持JDBC连接的数据库(如MySQL、Oracle等),以及Java开发...
在使用PowerBuilder (PB) 9.0进行应用程序开发时,有时我们需要将文件保存到数据库中,以便于数据管理和检索。这个过程涉及到文件操作、数据库交互以及数据存储格式的转换。下面将详细介绍如何在PB9.0中实现“把文件...
本文将详细讲解如何将图片以字节流的形式存入数据库,然后从数据库中取出并显示。我们将以一个名为"SaveGetPicture_Demo"的示例项目作为参考,探讨这一过程。 首先,我们需要理解什么是字节流。字节流是计算机处理...
从数据库取出图片并显示: 1. 查询数据:使用SQL查询语句从数据库中获取图片的二进制数据。 2. 将二进制数据还原为图片:将查询结果中的二进制数据转换回图片,可以使用`System.Drawing.Image.FromStream()`方法。 3...
本文将深入探讨如何将多媒体文件保存到数据库中以及如何从数据库中检索并显示这些文件,结合给定的标签和文件列表,我们将关注多媒体技术、数据库操作、控件使用以及源码分析。 首先,多媒体技术是指利用计算机处理...
本话题主要关注如何将图片保存到数据库中,然后从数据库中取出并显示在DataList控件上。这是一个多步骤的过程,涉及到数据库设计、图像处理、Web编程以及前端展示等多个环节。 首先,我们需要了解为什么要把图片...
`imgdemo`可能是一个示例程序或者一个包含处理图片的测试脚本,用于演示如何将图片转换为Base64,存储到数据库,然后从数据库中取出并回显到浏览器。 7. **安全性与性能考虑**: 尽管Base64编码方便了图片的存储...
在IT领域,将图片保存到数据库是一个常见的需求,尤其是在Web应用和移动应用中,为了方便管理和访问,开发者经常需要将用户的头像、产品图片、证书等图像数据存储在数据库中。这一过程涉及到图像的编码、解码以及...
本篇文章将详细探讨如何使用C#将图片文件保存到MSSQL数据库中。 首先,我们需要了解MSSQL数据库的基本操作。SQL Server是微软公司提供的一个关系型数据库管理系统,它支持多种数据类型,如VARCHAR(MAX)、VARBINARY...
综上所述,通过C#编程,我们可以实现将任意文件转换为字符串并存储到数据库,以及从数据库取出字符串后还原为文件,并利用AES加密保证文件的安全性。这一技术在数据备份、云存储、文件传输等领域有着广泛的应用。在...
// 将图像数据保存到数据库中... } ``` - 然后,可以使用`PictureBox`控件来显示从数据库中检索出的图像。 通过以上步骤,我们可以有效地在.NET Web应用程序或Windows Forms应用程序中实现图像数据的存储和检索...
最后,通过`adotable1.Post`提交更改,将文件保存到数据库中。 #### - 按钮点击事件:从数据库中取出文件 `Button2Click`事件处理程序负责从数据库中读取文件并将其保存到本地磁盘。`TBlobField(adotable1....
同时,如果要从数据库中取出Word文件,可以使用类似的步骤,但此时是使用SqlCommand的`ExecuteScalar`或`ExecuteReader`方法获取数据,然后将二进制数据写入到新的文件中。在处理大量数据时,还可以考虑使用存储过程...
这个小测试项目展示了如何通过Java处理图片流并将它们存储到数据库中,然后再取出。以下是关于这个过程的一些关键知识点: 1. **图片转二进制流**: 在Java中,我们可以使用`java.io`包中的`FileInputStream`或`...
这通常通过读取图片文件并将其加载到内存流对象中完成。然后,使用ADO的`Command`对象执行SQL INSERT语句,将流对象作为参数传递,将图片数据保存到`image`类型的字段。 2. **图片读取**:读取时,执行SQL SELECT...
你可以选择适合的控件,然后使用控件的DrawItem或OnPaint方法,结合CDC类的DrawBitmap功能,将从数据库中取出的BMP数据渲染到控件上。 9. 错误处理与资源管理:在处理过程中,必须注意异常处理和资源的正确释放,...
标题 "PB-数据库保存图片并在Datawindow中显示" 涉及到的是使用PowerBuilder(PB)这个开发工具,将图片数据存储在数据库中,并在DataWindow控件中进行显示的技术。下面,我们将深入探讨这一主题。 1. **Power...
这样,我们就完成了从数据库中取出二进制图片数据并将其保存为硬盘上的实际图片文件的过程。这个过程在很多应用场景中都很常见,比如网站后台管理系统、文件存储服务等。 总结一下,这个过程的关键知识点包括: 1. ...
这通常涉及从数据库查询结果中取出`byte[]`,然后使用流(`InputStream`)将其写入到图片输出流(如`OutputStream`)中,最后由前端展示。 描述中提到的“不是简单的保存上传图片的路径”,指的是这种方法不同于...
- 创建一个临时文件,使用`FileOpen`和`FileWrite`函数将内存缓冲区的数据写入文件,完成图片的保存。 3. **显示图片**: - 如果你想在PB9的窗口中直接显示图片,可以使用`Picture控件`。在查询结果集时,将BLOB...