小弟前段试着利用Bytea类型存取大对象,但是程序编好后测试发现虽然一个butea的属性可以存储高达1GB的二进制数据,但是它需要占用大量内存来完成这个大数据,实际中远达不到1G,上传一个大于13M的文件就会出现out of memory 或者connection is broken的异常,相当郁闷。当然也有可能是我程序的原因。
现在正在初试用oid这个类型来存取,修改程序后运行,却老出现invalid large-object descriptor: 0的异常,相当的郁闷闷!希望懂这方面的好心高手帮帮小弟,先谢谢您的大恩啦!QQ一直在线:254380172
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
fullfilename = ofd.FileName.ToString();
filename = Path.GetFileName(fullfilename);
NpgsqlConnection conn = new NpgsqlConnection("server=127.0.0.1;database=mydb;uid=postgres;pwd=1234");
conn.Open();
NpgsqlTransaction transaction = conn.BeginTransaction();
LargeObjectManager lom = new LargeObjectManager(conn);
conn.Open();
int noid = lom.Create(LargeObjectManager.READWRITE);
LargeObject lo = lom.Open(noid, LargeObjectManager.WRITE);
FileStream fs = File.OpenRead(fullfilename);
byte[] buf = new byte[fs.Length];
fs.Read(buf, 0, (int)fs.Length);
MessageBox.Show(conn.State.ToString());
lo.Write(buf);//错误提示出:ERROR: 42704: invalid large-object descriptor: 0
fs.Close();
lo.Close();
NpgsqlCommand command = new NpgsqlCommand("insert into file2(name, content) values(@name, @content)", conn);
command.Parameters.Add(new NpgsqlParameter("@name", NpgsqlTypes.NpgsqlDbType.Text));
command.Parameters.Add(new NpgsqlParameter("@content", NpgsqlTypes.NpgsqlDbType.Integer));
command.Parameters["@name"].Value = filename;
command.Parameters["@content"].Value = noid;
command.ExecuteNonQuery();
transaction.Commit();
conn.Close();
MessageBox.Show("上传文件成功!");
}
private void button2_Click(object sender, EventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
if (sfd.ShowDialog() == DialogResult.OK)
fullfilename = sfd.FileName.ToString();
filename = Path.GetFileName(fullfilename);
NpgsqlConnection conn = new NpgsqlConnection("server=127.0.0.1;database=mydb;uid=postgres;pwd=1234");
conn.Open();
NpgsqlTransaction transaction = conn.BeginTransaction();
LargeObjectManager lom = new LargeObjectManager(conn);
conn.Open();
//NpgsqlDataAdapter sda = new NpgsqlDataAdapter("select * from file2 where name = '" + filename + "'", conn);
//DataSet ds = new DataSet();
//sda.Fill(ds, "file2");
//int noid = (int)ds.Tables["file2"].Rows[0][1];
NpgsqlCommand cmd = new NpgsqlCommand("select content from file2 where name = '" + filename + "'", conn);
NpgsqlDataReader sdr = cmd.ExecuteReader();
int noid = sdr.GetInt32(1);
LargeObject lo = lom.Open(noid, LargeObjectManager.READ);
FileStream fs = File.OpenWrite(fullfilename);
byte[] buf = new byte[lo.Size()];
buf = lo.Read(lo.Size());
fs.Write(buf, 0, (int)lo.Size());
fs.Flush();
fs.Close();
lo.Close();
transaction.Commit();
DeleteLargeObject(noid);
//MemoryStream ms = new MemoryStream(buf);
//pictureBox1.Image = Image.FromStream(ms);
conn.Close();
MessageBox.Show("上传文件成功!");
}
public static void DeleteLargeObject(Int32 noid)
{
NpgsqlConnection conn = new NpgsqlConnection("server=127.0.0.1;database=mydb;uid=postgres;pwd=1234");
conn.Open();
NpgsqlTransaction t = conn.BeginTransaction();
LargeObjectManager lom = new LargeObjectManager(conn);
lom.Delete(noid);
t.Commit();
conn.Close(); }
现在正在初试用oid这个类型来存取,修改程序后运行,却老出现invalid large-object descriptor: 0的异常,相当的郁闷闷!希望懂这方面的好心高手帮帮小弟,先谢谢您的大恩啦!QQ一直在线:254380172
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
fullfilename = ofd.FileName.ToString();
filename = Path.GetFileName(fullfilename);
NpgsqlConnection conn = new NpgsqlConnection("server=127.0.0.1;database=mydb;uid=postgres;pwd=1234");
conn.Open();
NpgsqlTransaction transaction = conn.BeginTransaction();
LargeObjectManager lom = new LargeObjectManager(conn);
conn.Open();
int noid = lom.Create(LargeObjectManager.READWRITE);
LargeObject lo = lom.Open(noid, LargeObjectManager.WRITE);
FileStream fs = File.OpenRead(fullfilename);
byte[] buf = new byte[fs.Length];
fs.Read(buf, 0, (int)fs.Length);
MessageBox.Show(conn.State.ToString());
lo.Write(buf);//错误提示出:ERROR: 42704: invalid large-object descriptor: 0
fs.Close();
lo.Close();
NpgsqlCommand command = new NpgsqlCommand("insert into file2(name, content) values(@name, @content)", conn);
command.Parameters.Add(new NpgsqlParameter("@name", NpgsqlTypes.NpgsqlDbType.Text));
command.Parameters.Add(new NpgsqlParameter("@content", NpgsqlTypes.NpgsqlDbType.Integer));
command.Parameters["@name"].Value = filename;
command.Parameters["@content"].Value = noid;
command.ExecuteNonQuery();
transaction.Commit();
conn.Close();
MessageBox.Show("上传文件成功!");
}
private void button2_Click(object sender, EventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
if (sfd.ShowDialog() == DialogResult.OK)
fullfilename = sfd.FileName.ToString();
filename = Path.GetFileName(fullfilename);
NpgsqlConnection conn = new NpgsqlConnection("server=127.0.0.1;database=mydb;uid=postgres;pwd=1234");
conn.Open();
NpgsqlTransaction transaction = conn.BeginTransaction();
LargeObjectManager lom = new LargeObjectManager(conn);
conn.Open();
//NpgsqlDataAdapter sda = new NpgsqlDataAdapter("select * from file2 where name = '" + filename + "'", conn);
//DataSet ds = new DataSet();
//sda.Fill(ds, "file2");
//int noid = (int)ds.Tables["file2"].Rows[0][1];
NpgsqlCommand cmd = new NpgsqlCommand("select content from file2 where name = '" + filename + "'", conn);
NpgsqlDataReader sdr = cmd.ExecuteReader();
int noid = sdr.GetInt32(1);
LargeObject lo = lom.Open(noid, LargeObjectManager.READ);
FileStream fs = File.OpenWrite(fullfilename);
byte[] buf = new byte[lo.Size()];
buf = lo.Read(lo.Size());
fs.Write(buf, 0, (int)lo.Size());
fs.Flush();
fs.Close();
lo.Close();
transaction.Commit();
DeleteLargeObject(noid);
//MemoryStream ms = new MemoryStream(buf);
//pictureBox1.Image = Image.FromStream(ms);
conn.Close();
MessageBox.Show("上传文件成功!");
}
public static void DeleteLargeObject(Int32 noid)
{
NpgsqlConnection conn = new NpgsqlConnection("server=127.0.0.1;database=mydb;uid=postgres;pwd=1234");
conn.Open();
NpgsqlTransaction t = conn.BeginTransaction();
LargeObjectManager lom = new LargeObjectManager(conn);
lom.Delete(noid);
t.Commit();
conn.Close(); }
UP UP UP UP UP UP UP UP UP UP UP UP
这个返回多少, 是不是 0, 这个应该返回一个 > 0 的数值才对
期待回复
代码:buf = lo.Read(lo.Size()); // 这一句导致的修改为一次读取一个缓冲区大小, 写入文件, 循环直到结束, 就没事了我的垃圾代码片断: LargeObject lo = lbm.Open(noid, LargeObjectManager.READWRITE); FileStream fsout = File.OpenWrite("D:\\study.dbf.database");
int readed = 0;
int loPos = 0;
lo.Seek(0);
byte[] tempBuf = null;
do
{
tempBuf = lo.Read(4096);
readed = tempBuf.Length;
if (readed > 0)
{
fsout.Write(tempBuf, 0, readed);
loPos += readed;
lo.Seek(loPos);
}
} while (readed > 0);
fsout.Flush();
fsout.Close();
lo.Close();
t.Commit();
想问一下,您用昨天的代码上传一个大于90M的文件是没出错,而只有当读取它的时候才会出现异常吗?我再上传的时候就出现异常了!您的程序能打包发给我一份,让小弟好好学习学习吗?
还有刚才试着把上传那块代码改成块式存储,由于小弟水平有限,未能调试成功!能不能发个上传的块式存储代码,让我好好学习学习?
// 上传
void button18_Click(object sender, EventArgs e)
{
string arg = @"H:\ftp\D7Items.tar";
int bufSize = 4096;
using (NpgsqlConnection newcon = new NpgsqlConnection(UtilClass.connectionstring))
{
newcon.Open();
using (NpgsqlTransaction t = newcon.BeginTransaction())
{
LargeObjectManager lbm = new LargeObjectManager(newcon); int noid = lbm.Create(LargeObjectManager.READWRITE);
LargeObject lo = lbm.Open(noid, LargeObjectManager.WRITE); FileStream fs = File.OpenRead(arg);
byte[] buf = new byte[bufSize];
int readIn = 0;
do
{
readIn = fs.Read(buf, 0, bufSize);
lo.Write(buf);
} while (readIn > 0);
fs.Close();
lo.Close();
t.Commit();
txtLobId.Text = noid.ToString();
}
newcon.Close();
}
}
static void DeleteLargeObject(Int32 noid)
{
NpgsqlConnection conn = new NpgsqlConnection(UtilClass.connectionstring); conn.Open();
NpgsqlTransaction t = conn.BeginTransaction();
LargeObjectManager lbm = new LargeObjectManager(conn);
lbm.Delete(noid); t.Commit(); conn.Close(); } // lob download
void button19_Click(object sender, EventArgs e)
{
int loid = 0;
if (string.IsNullOrEmpty(txtLobId.Text))
return;
if (!int.TryParse(txtLobId.Text, out loid))
return;
using (NpgsqlConnection newcon = new NpgsqlConnection(UtilClass.connectionstring))
{
newcon.Open();
using (NpgsqlTransaction t = newcon.BeginTransaction())
{
LargeObjectManager lbm = new LargeObjectManager(newcon);
LargeObject lo = lbm.Open(loid, LargeObjectManager.READWRITE);
FileStream fsout = File.OpenWrite("D:\\temp.dat");
int readed = 0;
int loPos = 0;
lo.Seek(0);
byte[] tempBuf = null;
do
{
tempBuf = lo.Read(4096);
readed = tempBuf.Length;
if (readed > 0)
{
fsout.Write(tempBuf, 0, readed);
loPos += readed;
lo.Seek(loPos);
}
} while (readed > 0);
fsout.Flush();
fsout.Close();
lo.Close();
t.Commit();
}
}
} // log remove
void button20_Click(object sender, EventArgs e)
{
int loid = 0;
if (string.IsNullOrEmpty(txtLobId.Text))
return;
if (!int.TryParse(txtLobId.Text, out loid))
return; DeleteLargeObject(loid);
}
4096 有点慢, 你试试不同缓冲区大小,
我用了一个 123 兆的, 上传, 下载后, 还可以打开.
还有想问一下,大对象的实际内容看资料上说应该是存到一个pg_largeobject的系统表里,但我看了看我的数据库里都没有这个表,那么它存到什么地方了?能查看到它吗?能手动删除吗?
在 psql 中 \d pg_largeobject 可以看到这个表的定义,看文档说, 她将文件分割成一系列的 chunk 放到了这个表中, 实际存放文件内容的字段类型是 bytea!用户表那个 oid 的维护应该是你的责任吧?我的调用 deleteLargeObject 后, 数据库目录变小了, 你试试 VACUUM 一下?
再请教一下,删除数据前,是不是还要执行以下lo_unlink()呀?应怎样执行?
我的表file2(name text,content int)
PostgreSQL很开源,很强大!
Mr.花,THANK YOU!