I am trying to zip files to an SQL Server database table. I can't ensure that the user of the tool has write priveledges on the source file folder so I want to load the file into memory, compress it to an array of bytes and insert it into my database.
This below does not work.
class ZipFileToSql
{
public event MessageHandler Message;
protected virtual void OnMessage(string msg)
{
if (Message != null)
{
MessageHandlerEventArgs args = new MessageHandlerEventArgs();
args.Message = msg;
Message(this, args);
}
}
private int sourceFileId;
private SqlConnection Conn;
private string PathToFile;
private bool isExecuting;
public bool IsExecuting
{
get
{ return isExecuting; }
}
public int SourceFileId
{
get
{ return sourceFileId; }
}
public ZipFileToSql(string pathToFile, SqlConnection conn)
{
isExecuting = false;
PathToFile = pathToFile;
Conn = conn;
}
public void Execute()
{
isExecuting = true;
byte[] data;
byte[] cmpData;
//create temp zip file
OnMessage("Reading file to memory");
FileStream fs = File.OpenRead(PathToFile);
data = new byte[fs.Length];
ReadWholeArray(fs, data);
OnMessage("Zipping file to memory");
MemoryStream ms = new MemoryStream();
GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true);
zip.Write(data, 0, data.Length);
cmpData = new byte[ms.Length];
ReadWholeArray(ms, cmpData);
OnMessage("Saving file to database");
using (SqlCommand cmd = Conn.CreateCommand())
{
cmd.CommandText = @"MergeFileUploads";
cmd.CommandType = CommandType.StoredProcedure;
//cmd.Parameters.Add("@File", SqlDbType.VarBinary).Value = data;
cmd.Parameters.Add("@File", SqlDbType.VarBinary).Value = cmpData;
SqlParameter p = new SqlParameter();
p.ParameterName = "@SourceFileId";
p.Direction = ParameterDirection.Output;
p.SqlDbType = SqlDbType.Int;
cmd.Parameters.Add(p);
cmd.ExecuteNonQuery();
sourceFileId = (int)p.Value;
}
OnMessage("File Saved");
isExecuting = false;
}
private void ReadWholeArray(Stream stream, byte[] data)
{
int offset = 0;
int remaining = data.Length;
float Step = data.Length / 100;
float NextStep = data.Length - Step;
while (remaining > 0)
{
int read = stream.Read(data, offset, remaining);
if (read <= 0)
throw new EndOfStreamException
(String.Format("End of stream reached with {0} bytes left to read", remaining));
remaining -= read;
offset += read;
if (remaining < NextStep)
{
NextStep -= Step;
}
}
}
}