Avatar billede casper_skovgaard Nybegynder
29. januar 2005 - 14:43 Der er 11 kommentarer og
1 løsning

Hvordan gemmer jeg en fil i MySQL

Jeg skal kunne uploade/gemme en fil i min MySQL database. Indtil videre har jeg følgende kode:

HttpPostedFile myFile = filUpload.PostedFile;

if( myFile != null )
{
    // Get size of uploaded file
    int nFileLen = myFile.ContentLength;

    // Allocate a buffer for reading of the file
    byte[] myData = new byte[nFileLen];

    // Read uploaded file from the Stream
    myFile.InputStream.Read(myData, 0, nFileLen);

    string strFileName = Path.GetFileName(myFile.FileName);

    string strQuery = "INSERT INTO tblFiles SET FileName='" + strFileName + "',FileSize=" + myData.Length + ",ContentType='" + myFile.ContentType + "',FileData='" + myData + "'";

    // Store it in database
    SystemDatabase.ExecuteQuery( strQuery);

}


Der bliver fint oprettet en række i tabellen, men feltet FileData indeholder kun "System.Byte[]"...

Så hvordan uploader jeg så min fil? Jeg bruger MySQL Connector/Net
Avatar billede arne_v Ekspert
29. januar 2005 - 14:45 #1
Du kan ikke indsætte binære data på den måde.
Avatar billede arne_v Ekspert
29. januar 2005 - 14:46 #2
Du skal bruge parameters:

Eksempel:

using System;
using System.IO;
using System.Data;
using System.Data.SqlClient;

class MainClass
{
    public static void Main(string[] args)
    {
        // connect
        SqlConnection con = new SqlConnection("server=ARNEPC2\\ARNEPC2RUN;Integrated Security=SSPI;database=TestMSDE");
        con.Open();
       
        // create table
        SqlCommand cre = new SqlCommand("CREATE TABLE imgtest (id INTEGER PRIMARY KEY,img IMAGE)", con);
        cre.ExecuteNonQuery();

        // file -> byte array
        Stream imgfile = new FileStream(@"C:\blue.jpg", FileMode.Open);
        byte[] imgdata = new byte[(int)imgfile.Length];
        imgfile.Read(imgdata, 0, imgdata.Length);
        imgfile.Close();
       
        // insert
        SqlCommand ins = new SqlCommand("INSERT INTO imgtest VALUES(@id,@img)", con);
        ins.Parameters.Add("@id", SqlDbType.Int);
        ins.Parameters.Add("@img", SqlDbType.Image);
        ins.Parameters["@id"].Value = 1;
        ins.Parameters["@img"].Value = imgdata;
        ins.ExecuteNonQuery();

        // select
        SqlCommand sel = new SqlCommand("SELECT img FROM imgtest WHERE id = @id", con);
        sel.Parameters.Add("@id", SqlDbType.Int);
        sel.Parameters["@id"].Value = 1;
        byte[] imgdata2 = (byte[])sel.ExecuteScalar();
       
        // drop table
        SqlCommand drp = new SqlCommand("DROP TABLE imgtest", con);
        drp.ExecuteNonQuery();
       
        // byte array -> file
        Stream imgfile2 = new FileStream(@"C:\blue2.jpg", FileMode.Create);
        imgfile2.Write(imgdata2, 0, imgdata2.Length);
        imgfile2.Close();

        // disconnect
        con.Close();
    }
}
Avatar billede arne_v Ekspert
29. januar 2005 - 14:47 #3
og:

using System;
using System.Threading;
using System.Data;
using ByteFX.Data.MySqlClient;

public class PicTestThread
{
    private int n;
    private int npics;
    private int picsize;
    public PicTestThread(int n, int npics, int picsize)
    {
        this.n = n;
        this.npics = npics;
        this.picsize = picsize;
    }
    public void Run()
    {
        PicTest.CheckN(n, npics, picsize);
    }
}

public class PicTest
{
    private const int N = 10000;
    public static void CreateTable(int npics, int picsize)
    {
        MySqlConnection con = new MySqlConnection("Database=Test;Data Source=localhost;User Id=;Password=");
        con.Open();
        MySqlCommand cre = new MySqlCommand("CREATE TABLE pics (id INTEGER PRIMARY KEY, pic MEDIUMBLOB)", con);
        cre.ExecuteNonQuery();
        MySqlCommand ins = new MySqlCommand("INSERT INTO pics VALUES (@id, @pic)", con);
        ins.Parameters.Add("@id", MySqlDbType.Int);
        ins.Parameters.Add("@pic", MySqlDbType.MediumBlob);
        for(int i = 0; i < npics; i++)
        {
            ins.Parameters["@id"].Value = i;
            byte[] data = new Byte[picsize];
            for(int j = 0; j < picsize; j++)
            {
                data[j] = (byte)((i + j) % 256);
            }
            ins.Parameters["@pic"].Value = data;
            ins.ExecuteNonQuery();
        }
        con.Close();
    }
    public static void CheckOne(int id, int picsize)
    {
        MySqlConnection con = new MySqlConnection("Database=Test;Data Source=localhost;User Id=;Password=");
        con.Open();
        MySqlCommand sel = new MySqlCommand("SELECT pic FROM pics WHERE id = " + id, con);
        byte[] data = (byte[])sel.ExecuteScalar();
        if(data.Length != picsize)
        {
            Console.WriteLine("picture #" + id + " corrupted");
        }
        for(int j = 0; j < data.Length; j++)
        {
            if(((id + j) % 256) != data[j])
            {
                Console.WriteLine("picture #" + id + " corrupted");
            }
        }
        con.Close();
    }
    public static void DropTable()
    {
        MySqlConnection con = new MySqlConnection("Database=Test;Data Source=localhost;User Id=;Password=");
        con.Open();
        MySqlCommand drp = new MySqlCommand("DROP TABLE pics", con);
        drp.ExecuteNonQuery();
        con.Close();
    }
    public static void CheckN(int n, int npics, int picsize)
    {
        Random rng = new Random();
        for(int i = 0; i < n; i++)
        {
            int id = rng.Next(npics);
            CheckOne(id, picsize);
        }
    }
    public static void CheckTest(int nthreads, int npics, int picsize)
    {
        long t1 = DateTime.Now.Ticks;
        PicTestThread[] ptt = new PicTestThread[nthreads];
        Thread[] thr = new Thread[nthreads];
        for(int i = 0; i < thr.Length; i++)
        {
            ptt[i] = new PicTestThread(N/nthreads, npics, picsize);
            thr[i] = new Thread(new ThreadStart(ptt[i].Run));
        }
        for(int i = 0; i < thr.Length; i++)
        {
            thr[i].Start();
        }
        for(int i = 0; i < thr.Length; i++)
        {
            thr[i].Join();
        }
        long t2 = DateTime.Now.Ticks;
        Console.WriteLine(nthreads + " conc reqs, " +
                          npics + " pics in db, " +
                          picsize/1000 + " KB pics => " +
                          N/((t2 - t1) / 1000000.0) + " pics/sec");
    }
    public static void Main(string[] args)
    {
        int[] npics = { 250, 500, 1000 };
        int[] picsize = { 50000 /*, 100000, 200000 */ };
        int[] nthreads = { 10, 20, 40 };
        for(int i = 0; i < npics.Length; i++)
        {
            for(int j = 0; j < picsize.Length; j++)
            {
                CreateTable(npics[i], picsize[j]);
                for(int k = 0; k < nthreads.Length; k++)
                {
                    CheckTest(nthreads[k], npics[i], picsize[j]);
                }
                DropTable();
            }
        }
    }
}
Avatar billede arne_v Ekspert
29. januar 2005 - 14:48 #4
Det første eksempel er SQLServer, men MySQL er helt lige sådan.

Det sidste eksempel er lidt stort men kig i CreateTable metoden.
Avatar billede casper_skovgaard Nybegynder
29. januar 2005 - 15:49 #5
tak arne, jeg prøver lige om det virker. Men ved du hvilken datatype jeg skal bruger, så vidt jeg kan se findes IMAGE datatypen ikke i MySQL.
Avatar billede arne_v Ekspert
29. januar 2005 - 16:04 #6
Se sidste eksempel.

MySqlDbType.Blob
MySqlDbType.MediumBlob
MySqlDbType.LongBlob
Avatar billede casper_skovgaard Nybegynder
29. januar 2005 - 16:30 #7
hmm, kan ikke helt få det til at virke. Jeg har følgende kode:

private void WriteToDB(string strFileName, string strContentType, ref byte[] Buffer)
{
    string strConnectionString = "Server=XXX; Port=3306; Database=XXX; uid=XXX; pwd=XXX;";
    MySqlConnection con = new MySqlConnection( strConnectionString);

    con.Open();
     
    MySqlCommand ins = new MySqlCommand( "INSERT INTO tblFiles VALUES(@ID,@FileName,@FileSize,@ContentType,@FileData)", con);

    ins.Parameters.Add( "@ID", 10);
    ins.Parameters.Add( "@FileName", strFileName);
    ins.Parameters.Add( "@FileSize", Buffer.Length);
    ins.Parameters.Add( "@ContentType", strContentType);
    ins.Parameters.Add( "@FileData", Buffer);

    ins.ExecuteNonQuery();

    con.Close();
}

Men jeg får fejlen "Column 'FileName' cannot be null " selvom at strFileName har en værdi...

Er det ikke muligt at databasen selv sætter id'et?
Avatar billede arne_v Ekspert
29. januar 2005 - 16:35 #8
Skal

ins.Parameters.Add( "@ID", 10);

ikke være

ins.Parameters.Add("@id", MySqlDbType.Int);
ins.Parameters["@id"].Value = 10;

?
Avatar billede arne_v Ekspert
29. januar 2005 - 16:35 #9
Du kan sagtens lave id til et auto increment felt og så unlade at indsætte det
Avatar billede casper_skovgaard Nybegynder
29. januar 2005 - 17:04 #10
mærkeligt nu får jeg fejlen "Parameter '@ID' not found in collection" med følgende kode:

MySqlCommand ins = new MySqlCommand( "INSERT INTO tblFiles VALUES(@ID,@FileName,@FileSize,@ContentType,@FileData)", con);

ins.Parameters.Add( "@ID", MySqlDbType.Int16);
ins.Parameters.Add( "@FileName", MySqlDbType.VarChar);
ins.Parameters.Add( "@FileSize", MySqlDbType.Int16);
ins.Parameters.Add( "@ContentType", MySqlDbType.VarChar);
ins.Parameters.Add( "@FileData", MySqlDbType.LongBlob);

ins.Parameters["@ID"].Value = 16;
ins.Parameters["@FileName"].Value = strFileName;
ins.Parameters["@FileSize"].Value = Buffer.Length;
ins.Parameters["@ContentType"].Value = strContentType;
ins.Parameters["@FileData"].Value = Buffer;
Avatar billede casper_skovgaard Nybegynder
29. januar 2005 - 17:38 #11
Så fik jeg det til at virke :)

MySqlCommand ins = new MySqlCommand( "INSERT INTO tblFiles (FileName,FileSize,ContentType,FileData) VALUES(?FileName,?FileSize,?ContentType,?FileData)", con);

ins.Parameters.Add( "?FileName", strFileName);
ins.Parameters.Add( "?FileSize", Buffer.Length);
ins.Parameters.Add( "?ContentType", strContentType);
ins.Parameters.Add( "?FileData", Buffer);


Tusind tak for hjælpen arne, smid lige et svar, så du kan få dine velfortjente point :)
Avatar billede arne_v Ekspert
29. januar 2005 - 18:02 #12
svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester