IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Bases de données Delphi Discussion :

FileStream de SQL SERVER et Delphi


Sujet :

Bases de données Delphi

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2003
    Messages : 51
    Points : 60
    Points
    60
    Par défaut FileStream de SQL SERVER et Delphi
    Bonjour,

    Je dois réaliser une évolution qui consisterait en la mise en place d'un système de pièce jointe associé à des objets métiers.

    Le DBA ne veut pas :
    - stockage des fichiers en base (en même temps je le comprends)
    - stockage de l'adresse du fichier

    Il tient à ce que cela passe par le systême FileStream.

    J'ai tenté de gérer ce système en passant par une gestion de TBlobField traditionnel mais non ça ne fonctionne pas.

    D'après cette discussion, il faudrait utiliser l'API SQLFileStream...

    Sur le principe pas de problème mais quel uses faut-il utiliser sous D7 pour pouvoir l'utiliser cette API ?

    Merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    TBLOBField ne fonctionne pas, cela semble normal, il est conçu pour gérer un Binaire normal, les spécificités SQL Server doit être géré manuellement

    Si tu ne veux absolument pas de stockage brut, il va te falloir te plonger dans les méandres de la MSDN de SQL Server !
    Cela sera pénible et fastidieux !

    FILESTREAM c'est un stockage en fichier par Windows, au lieu de stocker un chemin, il stocke une adresse, il faudra vérifier le comportement si tu fais de la réplication, voire la migration d'un server à un autre



    Impossible d'envisager une table dédiée au stockage de BLOB (peut-être même une DB dédiée) et stockerais le fichier dans un binaire compressé ?

    Un simple SQL devrait fonctionner

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    CREATE TABLE aaa (ID_aaa INTEGER NOT NULL DEFAULT AUTOINCREMENT, ChampBinaire BINARY(32767));
     
    INSERT INTO aaa (ChampBinaire)
    VALUES (0xFFFFFFFFFF)

    Il te suffit d'encoder ton FileStream dans un AnsiString via BinToHex

    BINARY sera surement un peu court, passe au LONG BINARY

    Testé sur un vieux Sybase 10 et ADOQuery
    un SELECT renvoi un Blob qui se manipule sans problème !


    Pour l'utilisation par le nom de fichier, il existe des subtilités !

    Perso, je stockais les fichiers sur un serveur soit en LAN, mais mieux en FTP ou SFTP qui la gestion login\mdp pour sécuriser l'acces en r ou rw pour chaque utilisateur (et même un acces purement HTTP avec authentification pour la lecture seule)

    mon idée était d'utiliser une nommage automatique
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    \\Server\DBName\TableName\ID3\ID6\ID10\FileName
    Server = nom du server de fichier
    DBName = nom de la DB
    Table ...
    ID3 = c'est la clé primaire, généralement un INTEGER de 1 à 2147483647, paddé sur 10 cela donne 00000000001, ID3 correspond au 3 dernier chiffre 001, comme cela fait 1000 ou 10000 sous dossiers (c'est déjà bien assez long à afficher si l'on utilise l'explorateur)
    ID6 = 0000001
    ID10 = 00000000001
    FileName = juste le nom et l'extension du fichier (pas son chemin)
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2003
    Messages : 51
    Points : 60
    Points
    60
    Par défaut
    Re bonjour,

    Désolé mais je me suis mal exprimé, mon problème principal n'est pas le stockage via le filestream de SAL Server (enfin je crois ) mais de pouvoir récupérer mon fichier et l'ouvrir.

    Pour l'instant je me suis maquetté un petit prog qui charge les éléments de ma table dans un ListeView et qui sur un double clic sur l'item déclenche l'ouverture du fichier associé.
    Cela donne un truc comme ça (intégralité du code en PJ à ce message):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    // déclaration objet --> structure du dataset
        SPDoc: TMSStoredProc;
        SPDocDocID: TGuidField;
        SPDocDocNumber: TStringField;
        SPDocDocName: TStringField;
        SPDocDocDescription: TStringField;
        SPDocDocExtension: TStringField;
        SPDocDoc: TBlobField;
     
    // Implémentation
    // TLstPJ : Tcollection listant les fichiers
    // TPJ : item de la collection
    // PJ.Document est du type TStream généré par la méthode CreateBlobStream
    procedure TLStPJ.OuvrirFichier(index: integer);
    {=========================================================  Ouvre un fichier contenu dans le listview
    =========================================================}
    var
      PJ       : TPJ;
      FileName : string;
      StrFile  : TFileStream;
    begin
      PJ := IndexOf(index);
      if (Assigned(PJ))
      and (Assigned(PJ.Document)) then
      begin
        // Enregistrement du fichier dans le répertoire temporaire
        FileName := IncludeTrailingPathDelimiter(TWinUtilities.GetDirTemp) +
                    PJ.DocName +
                    PJ.DocExtension;
        if FileExists(FileName) then
          DeleteFile(FileName);
     
        StrFile  := TFileStream.Create(FileName,fmOpenRead or fmCreate);
        try
          PJ.Document.Seek(0, soFromBeginning);
          StrFile.CopyFrom(PJ.Document, PJ.Document.Size);
        finally
          StrFile.Free;
        end;
     
        ShellExecute(Application.Handle,'open',PChar(FileName),nil,nil,SW_SHOWNORMAL);
      end;
    end;
    Le souci, est que (par exemple sur des fichiers xls, xlsx) lors la lecture de PJ.Document.Size, j'ai un message IndexOutOfBound

    Je me suis fait également un autre programme avec une gestion blob standard (stockage des données dans un fichier xml du clientdataset), et là aucun probléme

    C'est pour cela que j'étais parti sur cette piste de l'API SQLFileStream
    Fichiers attachés Fichiers attachés

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    IndexOutOfBound c'est une erreur d'une List !
    IndexOf renvoie un objet ?
    Il renvoie -1 si non trouvé et la position normalement, c'est du code objet personnel ?

    ton objet Document existe correctement, tu ne le libère par inadvertance ?
    Pourquoi stocker ces stream dans une TCollection alors que tu as le TDataSet ?
    Tu utilise une sorte de couche objet pour gérer tes données comme on le ferait avec Bold ou ECO ?

    Tu utilise ADO ? BDE ? le comportement de CreateBlobStream est différent !
    En fait, je n'ai jamais dépassé une utilisation locale du Stream, je suppose que tu créés tes Stream en boucle que tu ajoutes à tes CollectionItem, mais je ne suis pas sur que le Stream pointe sur l'enregistrement à sa création et surtout dans quel état est le Stream après avoir fait un Next !
    Rien que cela, je ne lui ferais pas confiance !

    EDIT, j'ai lu ton ZIP
    Tu fais bien une boucle, déjà, j'aime pas trop, bcp d'objet créé pour rien, j'ai aussi fait de l'encaspulation de DataSet par une liste d'objet mais avec un système de lazyloading, c'est à dire que le Dataset reste interne à la liste et les objets sont créés par les accesseurs au moment opportun, lorsque tu 10000 lignes, inutiles de créer 10000 objet, souvent un seul suffit qui sert de curseur et un cache de quelques objets pour stocker les modifications locales ou les objets clonés !

    FMPJ.SPDoc.Close;
    Tu ne vois pas un problème dans le fait de fermer le DataSet qui contient les Stream ?

    Tu devrais recopier le BlobStream fourni par CreateBlobStream dans un TMemoryStream, libérer le BlobStream, et c'est le TMemoryStream qui tu ajoutes dans la Collection

    Ensuite, tu fais la fonction inverse qui va remplacer les BlobStream du DataSet par ceux de la Collection

    C'est un peu uzinagaz !
    Perso, je ne charge jamais les stream en permanence, je les charges au moment où j'en ai besoin, j'en stock le moins possible en mémoire (j'évite de faire un SELECT * FROM Table pour une table de 1000enr avec chaque des BLOB de 32K, c'est bcp de réseau consommé, de la mémoire utilisée sur le server et sur le client, surement totalement inutile
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2003
    Messages : 51
    Points : 60
    Points
    60
    Par défaut
    Ok, je vais simplifier mon code et tenir compte de tes remarques

    Merci

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2003
    Messages : 51
    Points : 60
    Points
    60
    Par défaut
    Nickel, une fois simplifié cela fonctionne sans souci !

    Merci
    Fichiers attachés Fichiers attachés

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Gestion des Temps dans Base Sql Server par Delphi
    Par BYALI dans le forum Bases de données
    Réponses: 4
    Dernier message: 09/03/2008, 14h09
  2. MS SQL Server 2000, Delphi 2005 ey Delphi 7
    Par Nzs26 dans le forum MS SQL Server
    Réponses: 0
    Dernier message: 05/03/2008, 11h31
  3. [MS SQL Server 2000 - Delphi 6 Ent. - ADO ]
    Par paca_mike dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 23/07/2005, 20h27
  4. Aider moi pour sql server et delphi
    Par aqs dans le forum Bases de données
    Réponses: 6
    Dernier message: 11/06/2005, 21h16
  5. Importer des données dans sql server avec DELPHI ???
    Par moutanakid dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 11/08/2004, 17h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo