Comment éviter la tâche FTP SSIS d'échouer quand il n'y a pas de fichiers à télécharger?

J'utilise SQL Server 2005, et je crée des tâches ftp dans SSIS.

parfois il y aura des fichiers à ftp, parfois non. S'il n'y a pas de fichiers, Je ne veux pas que la tâche ou le paquet échoue. J'ai changé la flèche passant de la tâche ftp à la suivante à "completion", donc le paquet passe à travers. J'ai changé le nombre d'erreurs autorisé à 4 (parce qu'il y a 4 tâches ftp, et n'importe lequel des 4 répertoires peut avoir ou ne pas avoir de fichiers).

mais, quand je cours le paquet d'un boulot d'agent, il marque le boulot comme un échec. Comme ça va se passer toutes les 15 minutes, je ne veux pas d'un tas de x rouges dans Mon historique de travail, ce qui nous fera ne pas voir un problème quand il se produit vraiment.

comment définir les propriétés dans la tâche ftp pour que ne pas trouver de fichiers sur ftp ne soit pas un échec? L'opération que j'utilise est "Envoyer des fichiers".

voici plus d'informations: les fichiers sont sur un serveur auquel je n'ai pas accès par l'intermédiaire de sauf ftp. Et je ne connais pas les noms de fichier à l'avance. L'utilisateur peut les appeler comme il veut. Donc je ne peux pas vérifier des fichiers spécifiques, ni, je pense, je peux vérifier du tout. Sauf en utilisant la connexion ftp et les tâches basées sur cette connexion. Les fichiers sont sur un serveur distant, et je veux les copier sur mon serveur, pour les obtenir à partir de ce serveur distant.

je peux shell un ftp de niveau de commande dans une tâche de script. C'est peut-être ce que je dois utiliser au lieu d'une tâche ftp. (J'ai changé pour utiliser la ligne de commande ftp, avec un fichier paramètre, appelé à partir d'une tâche de script. Il ne donne aucune erreur quand il n'y a pas des fichiers. Je pense que cette solution va marcher pour moi. Je crée le fichier de paramètres de manière dynamique, ce qui signifie que je n'ai pas besoin d'avoir des informations de connexion dans le fichier texte, mais peut plutôt être stocké dans mon fichier de configuration, qui est dans un endroit plus sûr.)

18
demandé sur thursdaysgeek 2008-09-26 21:36:37

12 réponses

je comprends que vous avez trouvé la réponse à votre question. C'est pour les autres utilisateurs qui pourraient trébucher sur cette question. Ici est une manière possible de parvenir à ce but. Script Task peut être utilisé pour trouver la liste des fichiers présents dans un chemin de dossier FTP pour un motif donné (dire *.txt). L'exemple ci-dessous montre comment cela peut être fait.

Étape-par-étape du processus:

  1. sur le paquet SSIS, créez un FTP Connection FTP et aussi de créer des 5 variables comme indiqué dans screenshot #1. Variable RemotePath contient le chemin du dossier FTP; LocalPath contient le dossier dans lequel les fichiers seront téléchargés;FilePattern contient le motif du fichier pour trouver la liste des fichiers à télécharger à partir du serveur FTP; FileName sera peuplé de Foreach loop container mais pour éviter L'erreur de temps de conception des tâches FTP, il peut être rempli avec / ou DelayValidation la propriété sur la tâche FTP peut être définie à True.

  2. sur le paquet SSIS, placez un Script Task, Foreach Loop container et FTP Task dans le Foreach Loop container comme montré dans screenshots # 2.

  3. Remplacer Main() méthode dans le Script Task avec le code dans le Script Code Des Tâches section. La tâche Script remplira la variable ListOfFiles avec la collection de fichiers correspondant à un modèle donné. Cet exemple utilisera d'abord modèle.* txt, ce qui ne donne aucun résultat, puis plus tard, le modèle *.xls qui correspondra à peu de fichiers sur le serveur FTP.

  4. Configurer le Foreach Loop container comme montré dans screenshots # 3 et # 4. Cette tâche passera par la variable **ListOfFiles*. S'il n'y a pas de fichiers, la tâche FTP à l'intérieur du conteneur de boucle ne sera pas exécutée. S'il y a des fichiers, la tâche FTP à l'intérieur du conteneur de boucle sera exécutée pour la tâche du nombre de fichiers trouvé sur le serveur FTP.

  5. Configurer le FTP Task comme montré dans screenshots # 5 et # 6.

  6. Capture d'écran # 7 affiche l'exécution d'un exemple de paquet quand aucun les fichiers de correspondance sont trouvés pour le motif *.txt.

  7. Capture d'écran # 8 affiche le contenu du dossier C:\temp\avant exécution de la paquet.

  8. Capture d'écran # 9 affiche l'exécution du paquet échantillon lorsque les fichiers de correspondance sont trouvés pour le motif *.xls.

  9. Capture d'écran # 10 affiche le contenu du chemin FTP remote/Practice/Directory_New.

  10. Capture d'écran # 11 affiche le contenu du dossier C:\temp\après exécution du paquet.

  11. Capture d'écran # 12 affiche la défaillance du paquet lorsqu'il est fourni avec chemin d'accès à Distance.

  12. Capture d'écran # 13 affiche le message d'erreur lié à la défaillance du paquet.

j'Espère que vous aide.

Script Code De Tâche:

C# code qui peut être utilisé dans SSIS 2008 and above.

inclure le using déclaration utilisation du système.Texte.RegularExpressions;

public void Main()
{
    Variables varCollection = null;
    ConnectionManager ftpManager = null;
    FtpClientConnection ftpConnection = null;
    string[] fileNames = null;
    string[] folderNames = null;
    System.Collections.ArrayList listOfFiles = null;
    string remotePath = string.Empty;
    string filePattern = string.Empty;
    Regex regexp;
    int counter;

    Dts.VariableDispenser.LockForWrite("User::RemotePath");
    Dts.VariableDispenser.LockForWrite("User::FilePattern");
    Dts.VariableDispenser.LockForWrite("User::ListOfFiles");
    Dts.VariableDispenser.GetVariables(ref varCollection);

    try
    {
        remotePath = varCollection["User::RemotePath"].Value.ToString();
        filePattern = varCollection["User::FilePattern"].Value.ToString();

        ftpManager = Dts.Connections["FTP"];
        ftpConnection = new FtpClientConnection(ftpManager.AcquireConnection(null));
        ftpConnection.Connect();
        ftpConnection.SetWorkingDirectory(remotePath);
        ftpConnection.GetListing(out folderNames, out fileNames);
        ftpConnection.Close();

        listOfFiles = new System.Collections.ArrayList();
        if (fileNames != null)
        {
            regexp = new Regex("^" + filePattern + "$");
            for (counter = 0; counter <= fileNames.GetUpperBound(0); counter++)
            {
                if (regexp.IsMatch(fileNames[counter]))
                {
                    listOfFiles.Add(remotePath + fileNames[counter]);
                }
            }
        }

        varCollection["User::ListOfFiles"].Value = listOfFiles;
    }
    catch (Exception ex)
    {
        Dts.Events.FireError(-1, string.Empty, ex.ToString(), string.Empty, 0);
        Dts.TaskResult = (int) ScriptResults.Failure;
    }
    finally
    {
        varCollection.Unlock();
        ftpConnection = null;
        ftpManager = null;
    }

    Dts.TaskResult = (int)ScriptResults.Success;
}

VB code qui peut être utilisé dans SSIS 2005 and above.

inclure le Imports déclaration Système D'Importation.Texte.RegularExpressions

Public Sub Main()
    Dim varCollection As Variables = Nothing
    Dim ftpManager As ConnectionManager = Nothing
    Dim ftpConnection As FtpClientConnection = Nothing
    Dim fileNames() As String = Nothing
    Dim folderNames() As String = Nothing
    Dim listOfFiles As Collections.ArrayList
    Dim remotePath As String = String.Empty
    Dim filePattern As String = String.Empty
    Dim regexp As Regex
    Dim counter As Integer

    Dts.VariableDispenser.LockForRead("User::RemotePath")
    Dts.VariableDispenser.LockForRead("User::FilePattern")
    Dts.VariableDispenser.LockForWrite("User::ListOfFiles")
    Dts.VariableDispenser.GetVariables(varCollection)

    Try

        remotePath = varCollection("User::RemotePath").Value.ToString()
        filePattern = varCollection("User::FilePattern").Value.ToString()

        ftpManager = Dts.Connections("FTP")
        ftpConnection = New FtpClientConnection(ftpManager.AcquireConnection(Nothing))

        ftpConnection.Connect()
        ftpConnection.SetWorkingDirectory(remotePath)
        ftpConnection.GetListing(folderNames, fileNames)
        ftpConnection.Close()

        listOfFiles = New Collections.ArrayList()
        If fileNames IsNot Nothing Then
            regexp = New Regex("^" & filePattern & "$")
            For counter = 0 To fileNames.GetUpperBound(0)
                If regexp.IsMatch(fileNames(counter)) Then
                    listOfFiles.Add(remotePath & fileNames(counter))
                End If
            Next counter
        End If

        varCollection("User::ListOfFiles").Value = listOfFiles

        Dts.TaskResult = ScriptResults.Success

    Catch ex As Exception
        Dts.Events.FireError(-1, String.Empty, ex.ToString(), String.Empty, 0)
        Dts.TaskResult = ScriptResults.Failure
    Finally
        varCollection.Unlock()
        ftpConnection = Nothing
        ftpManager = Nothing
    End Try

    Dts.TaskResult = ScriptResults.Success
End Sub

Capture d'écran #1:

1

Capture d'écran #2:

2

Capture d'écran #3:

3

Capture d'écran #4:

4

Capture d'écran #5:

5

Capture d'écran #6:

6

Capture d'écran #7:

7

Capture d'écran n ° 8:

8

Capture d'écran n ° 9:

9

Capture d'écran n ° 10:

10

Capture d'écran #11:

11

Capture d'écran # 12:

12

Capture d'écran n ° 13:

13

14
répondu 2011-07-16 07:14:00

Cochez cette lien qui décrit comment gérer avec élégance les erreurs de tâche dans le paquet SSIS.

j'ai eu presque le même problème mais, avec la récupération des dossiers. Je voulais que le paquet ne tombe pas en panne quand aucun fichier N'a été trouvé sur le serveur FTP. Le lien ci-dessus empêche l'erreur de bouillonner et de causer l'échec du paquet; quelque chose que vous auriez pensé que FailPackageOnError=false aurait dû faire? :- S

espérons que cela résolve pour vous aussi!

13
répondu 2011-07-26 17:06:41

je viens d'avoir ce numéro, après avoir lu certaines des réponses ici, rien n'a vraiment réglé mon problème et les solutions ici semblent insensées en termes de complexité.

ma tâche FTP échouait car je n'autorisais pas la réécriture de fichiers, disons que le travail a été lancé deux fois de suite, la première passe sera très bien, parce que certains fichiers sont transférés mais échoueront si un fichier local existe déjà.

ma solution était simple:

  1. clic Droit tâche-propriétés
  2. Set Foreceexecutionresult = "Success"
4
répondu tribe84 2015-10-16 13:37:48

ce n'est peut-être pas la meilleure solution, mais cela fonctionne.

j'utilise une tâche de script, et j'ai un tas de variables pour les informations de connexion ftp, et les répertoires source et destination. (Parce que, nous allons changer le serveur sur lequel il est lancé, et il sera plus facile de le changer dans un paquet de configuration.)

j'ai créer un fichier texte à la volée, et d'écrire les commandes ftp c':

    Dim ftpStream As StreamWriter = ftpFile.CreateText()
    ftpStream.WriteLine(ftpUser)
    ftpStream.WriteLine(ftpPassword)
    ftpStream.WriteLine("prompt off")
    ftpStream.WriteLine("binary")
    ftpStream.WriteLine("cd " & ftpDestDir)
    ftpStream.WriteLine("mput " & ftpSourceDir)
    ftpStream.WriteLine("quit 130")
    ftpStream.Close()

Puis, après avoir donné assez de temps pour vraiment fermer, je commence un processus pour la commande ftp:

    ftpParameters = "-s:" & ftpParameterLoc & ftpParameterFile & " " & ftpServer
    proc = System.Diagnostics.Process.Start("ftp", ftpParameters)

puis, après lui avoir donné plus de temps pour que le processus ftp s'exécute, j'efface le fichier ftp temporaire (qui contient des informations de connexion!).

Si les fichiers n'existent pas dans le répertoire source (la variable a l' \\\dir\*.* cartographie), alors il n'y a pas d'erreur. Si une autre erreur se produit, la tâche échoue encore, comme il devrait.

je suis nouveau au SSIS, et c'est peut-être un kludge. Mais il fonctionne pour l'instant. Je suppose que j'ai demandé pour le mieux, et je vais certainement pas prétendre que c'est elle.

Comme je l'ai souligné, je n'ai aucun moyen de savoir ce que les fichiers sont nommés, ou même s'il y a des fichiers à tous. Si elles sont là, je veux obtenir.

3
répondu thursdaysgeek 2011-07-26 17:07:31

je n'ai pas emballé réponse pour vous, mais puisque personne n'a posté sur ce sujet...

vous devriez pouvoir définir une variable dans une tâche de script ActiveX et ensuite l'utiliser pour décider si la tâche FTP doit être exécutée ou non. Il est un exemple ici cela fonctionne avec les chemins locaux. Avec un peu de chance, vous pouvez adapter le concept (ou si possible, mapper le lecteur FTP et le faire de cette façon).

1
répondu Tom H 2008-09-26 18:22:08

1) Définir la propriété de la tâche FTP Pourexecutionresult = Success

2) ajouter ce code à la tâche FTP onerror event handler.

    public void Main()
    {
        // TODO: Add your code here

        int errorCode = (int)Dts.Variables["System::ErrorCode"].Value;

        if (errorCode.ToString().Equals("-1073573501"))
        {
            Dts.Variables["System::Propagate"].Value = false;
        }
        else
        {
            Dts.Variables["System::Propagate"].Value = true;
        }


        Dts.TaskResult = (int)ScriptResults.Success;
    }
1
répondu Todd Hoffert 2018-02-15 21:25:38

le mettre dans un container ForEach, qui itère sur les fichiers à télécharger. Pas de fichiers, PAS de FTP, pas d'échec.

0
répondu Meff 2008-09-26 20:38:54

vous pouvez rediriger en cas d'échec, vers une autre tâche qui ne fait rien, c'est à dire un script qui retourne juste true.

pour ce faire, ajoutez la nouvelle tâche script, mettez en surbrillance votre tâche FTP, un deuxième connecteur vert apparaîtra, faites glisser cela à la tâche script, puis double-cliquez dessus. Sélectionnez Failure sur la liste déroulante. Évidemment, vous aurez alors besoin de gérer les échecs réels dans cette tâche de script pour toujours afficher dans l'historique de travail.

0
répondu baldy 2008-10-02 14:00:48

Ah, OK Merci pour les précisions. Comme la tâche FTP ne peut pas retourner une liste de dossiers, il ne sera pas possible d'utiliser la ForEach comme je l'ai dit initialement - qui ne fonctionne que si vous téléchargez X quantité de fichiers vers une source distante.

pour télécharger X quantité de fichiers, vous pouvez aller de deux façons, soit vous pouvez le faire entièrement dans .Net dans une tâche de script, ou vous pouvez peupler un ArrayList avec les noms de fichiers à partir de L'intérieur D'une tâche de script .Net, puis ForEach au-dessus de L'ArrayList, en passant le nom de fichier à une variable et le téléchargement du nom de cette variable dans une tâche FTP standard.

exemple de Code à suivre:http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=2472491&SiteID=1

ainsi, dans ce qui précède, vous obtiendriez les noms de fichier() et peupleriez le tableau à partir de cela, puis assigneriez le tableau à une variable de type D'objet dans Dts.Variables, puis prévenir sur cet objet (ArrayList) variable en utilisant le code quelque chose comme: http://www.sqlservercentral.com/articles/SSIS/64014/

0
répondu Meff 2008-10-02 14:19:39

vous pouvez utiliser la tâche FTP SSIS libre++ de eaSkills. Il ne jette pas une erreur si le fichier ou les fichiers n'existent pas, il supporte les jokers et vous donne l'option de télécharger et supprimer si vous avez besoin de le faire.

voici le lien vers la page principale: http://www.easkills.com/ssis/ftptask

0
répondu Kilani 2010-03-10 06:39:53

c'est une autre solution qui fonctionne pour moi, en utilisant des trucs intégrés et donc sans réécriture manuelle de la logique FTP:

1) créez une variable dans votre paquet appelée FTP_Error

2) Cliquez sur votre tâche FTP, puis cliquez sur" Event Handlers " onglet

3) Cliquez dans la page pour créer un gestionnaire d'événements pour "FTP Task / OnError" - cela se déclenche chaque fois qu'il y a des problèmes avec le FTP

4) de la boîte à outils, faites glisser un élément de tâche Script, et double-cliquez pour l'ouvrir

5) dans la première pop-up, ReadOnlyVariables - add System:: ErrorCode, System:: ErrorDescription

6) dans la première fenêtre pop-up, ReadWriteVariables-ajouter votre variable User::FTP_Error

8) dans le script, définissez votre variable FTP_Error pour contenir les variables ReadOnlyVariables que nous avions ci-dessus:

Dts.Variables["FTP_Error"].Value = "ErrorCode:" + Dts.Variables["ErrorCode"].Value.ToString() + ", ErrorDescription=" + Dts.Variables["ErrorDescription"].Value.ToString();

9) enregistrer et fermer le script

10) Appuyez sur "OK" pour script tâche

11) retourner à l'onglet "Flux de contrôle"

12) de la tâche FTP, OnError aller à une nouvelle tâche Script, et éditer que

13) ReadOnlyVariables: User:: FTP_Error from before

14) Maintenant, quand il n'y a pas de fichiers trouvés sur le FTP, le code d'erreur est -1073573501 (vous pouvez trouver la référence des codes d'erreur de la liste ici: http://msdn.microsoft.com/en-us/library/ms345164.aspx)

15) dans votre script, mettez la logique pour faire ce que vous voulez - si vous trouvez un " no files j'ai trouvé "code", alors peut-être vous dites tâche réussie. Si non, alors la tâche a échoué. Et votre flux normal pouvez gérer ce que vous voulez:

if (Dts.Variables["FTP_Error"].Value.ToString().Contains("-1073573501"))
{
  // file not found - not a problem
  Dts.TaskResult = (int)ScriptResults.Success;
}
else
{
  // some other error - raise alarm!
  Dts.TaskResult = (int)ScriptResults.Failure;
}

et à partir de là votre flux réussi/échoué fera ce que vous voulez en faire.

0
répondu Chad 2012-02-20 15:20:13

Une alternative est d'utiliser ce recenseur de fichiers FTP enter image description here

0
répondu Joost 2012-07-18 07:28:16