Как проверить / проверить, существует ли изображение в базе данных? - PullRequest
0 голосов
/ 15 сентября 2018

Я использую указанный код для проверки своего изображения.
К сожалению, мне не удалось этого сделать, и я впервые делаю проверку изображения.

Что-то не так в моей логике? Я что-то здесь забыл? Как правильно это делать.

Примечание:
Я сохраняю изображение как изображение, а не путь, а также тип данных Varbinary(MAX) в моей базе данных.

System.IO.FileNotFoundException: «Не удалось найти файл 'C: \ Users \ Andrea \ Source \ репо \ CapstoneSIMS \ CapstoneSIMS \ Bin \ Debug \ 72EF99A3668CF13820B113EB2E090C37716C9742' '

.

(я получаю эту ошибку при попытке вставить изображение)

public partial class ADDProduct : MetroForm
{
    SIMSProduct _view;

    public ADDProduct(SIMSProduct _view)
    {
        InitializeComponent();
        this._view = _view;                  
    }

    DataSet ds = new DataSet();
    DataTable dt = new DataTable();
    byte[] photobyte;

    public string CalculateHash(string filename)
    {
        SHA1CryptoServiceProvider crypt = new SHA1CryptoServiceProvider();
        //MD5CryptoServiceProvider crypt = new MD5CryptoServiceProvider();
        string hash = string.Empty;
        using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
        {
            byte[] checksum = crypt.ComputeHash(fs);
            foreach (byte b in checksum)
                hash += b.ToString("X2");
        }
        return (hash);
    }

    public static bool ImageExists(string filehash)
    {
        bool result = false;
        using (var connection = SQLConnection.GetConnection())
        {
            using (SqlCommand cmd = new SqlCommand("SELECT COUNT(0) FROM employee_product WHERE ImageHash = @ImageHash", connection))
            {
                connection.Open();
                int imagecount = (int)cmd.ExecuteScalar();
                result = imagecount == 0;
                connection.Close();
            }
        }
        return (result);
    }

    private void btn_add_Click(object sender, EventArgs e)
    {
        _view.ID = txt_id.Text;
        filehash = CalculateHash(@"C:\myimagefile.jpg");
        using (var con = SQLConnection.GetConnection())
        {
            if (string.IsNullOrEmpty(cbox_supplier.Text) || string.IsNullOrEmpty(txt_code.Text) || string.IsNullOrEmpty(txt_item.Text) || string.IsNullOrEmpty(txt_quantity.Text) || string.IsNullOrEmpty(txt_cost.Text) || pictureBox1.Image == null )
            {
                CustomNotifcation.Show("Please input the required fields", CustomNotifcation.AlertType.warning);
            }
            else
            {          
                ValidateCode.IsValidCode(txt_code,lbl_code,ds);
                string filehash = CalculateHash(pictureBox1.Tag.ToString());

                if (lbl_code.Visible == true)
                {
                    CustomNotifcation.Show("CODE ALREADY EXIST", CustomNotifcation.AlertType.error);
                    lbl_code.Visible = false;                      
                }
                else if (ImageExists(pictureBox1.Tag.ToString()))
                {
                    MessageBox.Show("image exists");
                    return;
                }
                else
                {
                    using (var select = new SqlCommand("Insert into employee_product (Image, ImageHash, ID, Supplier, Codeitem, Itemdescription, Date, Quantity, Unitcost) Values (@Image, @ID, @Supplier, @Codeitem, @Itemdescription, @Date, @Quantity, @Unitcost)", con))
                    {
                        var ms = new MemoryStream();
                        pictureBox1.Image.Save(ms, pictureBox1.Image.RawFormat);
                        photobyte = ms.GetBuffer();
                        select.Parameters.Add("@Image", SqlDbType.VarBinary).Value = photobyte;
                        select.Parameters.Add("@ImageHash", SqlDbType.VarChar, 50);
                        select.Parameters["@ImageHash"].Value = filehash;
                        select.Parameters.Add("@Supplier", SqlDbType.VarChar).Value = cbox_supplier.Text;
                        select.Parameters.Add("@Codeitem", SqlDbType.VarChar).Value = txt_code.Text.Trim();
                        select.Parameters.Add("@Itemdescription", SqlDbType.VarChar).Value = txt_item.Text.Trim();
                        select.Parameters.Add("@Date", SqlDbType.VarChar).Value = date;
                        select.Parameters.Add("@Quantity", SqlDbType.Int).Value = txt_quantity.Text.Trim();
                        select.Parameters.Add("@Unitcost", SqlDbType.Int).Value = txt_cost.Text.Trim();
                        select.ExecuteNonQuery();
                        CustomMessage.Show("Message: Item successfully added!",CustomMessage.Messagetype.Success);
                        pictureBox1.Image = null;
                        cbox_supplier.Items.Clear();
                        txt_code.Clear();
                        txt_item.Clear();
                        txt_quantity.Clear();
                        txt_cost.Clear();
                        _view.btn_update.Enabled = false;
                        _view.AddingProduct();
                        this.Close();
                    }
                }
            }
        }
    }

    private void pictureBox1_Click(object sender, EventArgs e)
    {
         var opnfd    = new OpenFileDialog();
        opnfd.Filter            = "Image Files (*.jpg;*.jpeg;.*.png;)|*.jpg;*.jpeg;.*.png;";
        opnfd.Title             = "Select Item";

        if (opnfd.ShowDialog() == DialogResult.OK)
        {
            pictureBox1.SizeMode    = PictureBoxSizeMode.StretchImage;
            pictureBox1.Image       = Image.FromFile(opnfd.FileName);
            CalculateHash(opnfd.FileName);
        }
    }
}


My DATABASE

Ответы [ 4 ]

0 голосов
/ 15 сентября 2018
using (var con = SQLConnection.GetConnection())
{
    using (var select = new SqlCommand(SELECT COUNT(0) FROM employee_product WHERE Image = @Image, con))
    {
        cmd.Parameters.Add("@Image", SqlDbType.VarBinary).Value = PhotoByte;
        int count = (int)select.ExecuteScalar();
        if (count > 0 ) 
        {
            lbl.Show();
        }
    }
}
0 голосов
/ 15 сентября 2018

Вы можете рассчитать MD5 / SHA1 изображения и сохранить его в отдельном столбце таблицы, затем, когда вы придете, чтобы проверить, существует ли изображение, вы рассчитаете MD5 / SHA1 текущего изображения, а затем убедитесь, что оно соответствуетв базе данных.Максимальный размер MD5 / SHA1 должен составлять около 50 символов, и он должен быть уникальным для каждого изображения (столкновения MD5 наблюдались, и я думаю, что SHA1 также имел место, но вряд ли вы вставите миллионы изображений в вашу БД).

Ваша таблица будет выглядеть следующим образом:

ID INT
Image VARBINARY(MAX)
ImageHash VARCHAR(50)

плюс любые другие необходимые вам столбцы.

Чтобы рассчитать MD5 / SHA1 для изображения, вы будете использовать это:

public string CalculateHash(string filename)
{
    SHA1CryptoServiceProvider crypt = new SHA1CryptoServiceProvider();
    //MD5CryptoServiceProvider crypt = new MD5CryptoServiceProvider();
    string hash = string.Empty;
    using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
    {
        byte[] checksum = crypt.ComputeHash(fs);
        foreach (byte b in checksum)
            hash += b.ToString("X2");
    }

    return(hash);
}

Приведенный выше метод использует криптографический расчет SHA1.Если вы предпочитаете использовать MD5 (немного быстрее), закомментируйте строку SHA1 и раскомментируйте строку MD5.

Call it with:

string filehash = CalculateHash(@"C:\myimagefile.jpg");

Затем, когда вы хотите проверить, вставлено ли ваше изображение, вы можете использовать запрос:

SELECT COUNT(0) FROM employee_product WHERE ImageHash = @ImageHash

Установите параметр вашего запроса на:

cmd.Parameters.Add("@ImageHash", SqlDbType.Varchar, 50);
cmd.Parameters["@ImageHash"].Value = filehash;

Затем вызовите:

int result = (int)cmd.ExecuteScalar();
if (result == 0)
{
    // Insert your image, don't forget to insert the filehash into the ImageHash column or subsequent checks will always fail.
}

Это гораздо более быстрый способ проверить, что изображениесуществует, поскольку вы отправляете в базу данных только 50 символов для проверки, а не целое изображение.

Таким образом, вы создадите новый метод для поиска в базе данных наличия изображения:

public bool ImageExists(string filehash)
{
    bool result = false;
    using (SqlConnection connection = SQLConnection.GetConnection())
    {
        using (SqlCommand cmd = new SqlCommand("SELECT COUNT(0) FROM employee_product WHERE ImageHash = @ImageHash", connection))
        {
            connection.Open();
            int imagecount = (int)cmd.ExecuteScalar();
            result = imagecount == 0;
            connection.Close();
        }
    }

    return(result);
}

Затем в вашем методе AddProduct непосредственно перед этой строкой:

using (var select = new SqlCommand("Insert into employee_product (Image, ID, Supplier, Codeitem, Itemdescription, Date, Quantity, Unitcost) Values (@Image, @ID, @Supplier, @Codeitem, @Itemdescription, @Date, @Quantity, @Unitcost)", con))

Вы можете вставить:

string filehash = CalculateHash(imagefilename);
if (ImageExists(filehash)
{
    MessageBox.Show("Image already exists");
    return;
}

// the rest of your code goes here including adding a parameter to take the ImageHash.

Когда вы читаете файл образа с диска (я предполагаю, что этооткуда вы получаете изображение), тогда вы можете сохранить имя файла в объекте PictureBox.Tag.Затем извлеките это имя файла (включая путь) из PictureBox.Tag и передайте его в ImageExists:

string filehash = CalculateHash(pictureBox1.Tag.ToString());

Чтобы поместить имя файла в поле для рисунков, используйте:

using(OpenFileDialog ofd = new OpenFileDialog())
{
    if (ofd.ShowDialog() == DialogResult.OK)
    {
        pictureBox1.Image = Image.FromFile(ofd.FileName);
        pictureBox1.Tag = ofd.FileName;
    }
}

В качестве альтернативы вы можетеВыполните вычисление хеша, когда пользователь загружает изображение и сохраняет его в теге:

using(OpenFileDialog ofd = new OpenFileDialog())
{
    if (ofd.ShowDialog() == DialogResult.OK)
    {
        pictureBox1.Image = Image.FromFile(ofd.FileName);
        pictureBox1.Tag = CalculateHash(ofd.FileName);
    }
}

Затем при вызове ImageExists используйте:

if (ImageExists(pictureBox1.Tag.ToString()))
{
    MessageBox.Show("image exists");
    return;
}
0 голосов
/ 15 сентября 2018
  • Сначала укажите длину VarBinary, потому что VarBinary без определенной длины имеет длину по умолчанию
  • Второе изменение Измените [ExecuteNonQuery] и используйте другую вещь, например [ExecuteReader] или [sqldataAdapter] или [SqlScalar]

     select.Parameters.Add("@Image", SqlDbType.VarBinary,[Length   VarBinary Column in database ]).Value = PhotoByte;
    

Хорошего дня

0 голосов
/ 15 сентября 2018

ExecuteNonQuery() - для операторов INSERT, UPDATE, DELETE и DDL, т. Е. Для команд, не возвращающих строки. Вы должны использовать ExecuteReader() и использовать возвращенный читатель для чтения возвращаемых данных вместо использования SqlDataAdapter. Или, что еще лучше, используйте утверждение типа

SELECT COUNT(*) FROM employee_product WHERE Image = @Image

И затем получить счет с ExecuteScalar():

using (var con = SQLConnection.GetConnection())
using (var cmd = new SqlCommand(sql, con)) {
    cmd.Parameters.Add("@Image", SqlDbType.VarBinary).Value = PhotoByte;
    con.Open();
    int count = (int)cmd.ExecuteScalar();
    if (count > 0 ) {
        ...
    }
}

ExecuteScalar() возвращает первый столбец первой строки набора результатов.

Но, вероятно, было бы более эффективно хранить хэш-код вместе с изображением и сравнивать хэш, а не сравнивать данные всего изображения. Хэш-код может быть даже проиндексирован для более быстрого доступа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...