18 Stimmen

Wie kann man verhindern, dass die SSIS-FTP-Aufgabe fehlschlägt, wenn keine Dateien zum Herunterladen vorhanden sind?

Ich verwende SQL Server 2005 und erstelle ftp-Aufgaben in SSIS.

Manchmal gibt es Dateien, die per FTP übertragen werden können, manchmal nicht. Wenn es keine Dateien gibt, möchte ich nicht, dass die Aufgabe oder das Paket fehlschlägt. Ich habe den Pfeil, der von der FTP-Aufgabe zur nächsten führt, auf "Abschluss" gesetzt, damit das Paket durchläuft. Ich habe die zulässige Anzahl von Fehlern auf 4 geändert (weil es 4 ftp-Aufgaben gibt und jedes der 4 Verzeichnisse Dateien enthalten kann oder auch nicht).

Wenn ich das Paket jedoch über einen Auftrag im Agenten ausführe, wird der Auftrag als fehlgeschlagen markiert. Da dieser Auftrag alle 15 Minuten ausgeführt wird, möchte ich nicht, dass ein Haufen roter X's in der Auftragshistorie auftauchen, was dazu führt, dass wir ein Problem nicht sehen, wenn es wirklich auftritt.

Wie stelle ich die Eigenschaften in der FTP-Aufgabe so ein, dass das Nichtfinden von Dateien für ftp kein Fehler ist? Die Operation, die ich verwende, ist "Dateien senden".

Hier einige weitere Informationen: Die Dateien befinden sich auf einem Server, zu dem ich nur über FTP Zugang habe. Und ich kenne die Dateinamen nicht im Voraus. Der Benutzer kann sie nennen, wie er will. Ich kann also nicht nach bestimmten Dateien suchen, und ich glaube, ich kann es auch gar nicht. Es sei denn, ich verwende die FTP-Verbindung und Aufgaben, die auf dieser Verbindung basieren. Die Dateien befinden sich auf einem entfernten Server, und ich möchte sie auf meinen Server kopieren, um sie von diesem entfernten Server abzurufen.

Ich kann einen ftp-Befehl in einer Skriptaufgabe ausführen. Vielleicht ist es das, was ich anstelle einer ftp-Aufgabe verwenden muss. (Ich bin dazu übergegangen, die ftp-Befehlszeile mit einer Parameterdatei zu verwenden, die von einer Skriptaufgabe aufgerufen wird. Es gibt keine Fehlermeldungen, wenn es keine Dateien zu holen gibt. Ich denke, dass diese Lösung für mich funktionieren wird. Ich erstelle die Parameterdatei dynamisch, was bedeutet, dass ich die Verbindungsinformationen nicht in der reinen Textdatei haben muss, sondern sie in meiner Konfigurationsdatei speichern kann, die sich an einem sichereren Ort befindet).

0 Stimmen

Wenn Sie Ihre Frage lesen, scheint es, dass Sie null bis viele Dateien lokal haben und diese per FTP an einen entfernten Standort übertragen möchten. Wenn ich mir Ihre Antwort ansehe, scheint es so, als ob Sie null bis viele Dateien am entfernten Standort haben und diese auf den lokalen Standort übertragen wollen. Könnten Sie das bitte klären? :)

0 Stimmen

Es waren null zu viele Dateien am entfernten Standort, und ich wollte sie auf den lokalen Standort bringen.

14voto

Ich verstehe, dass Sie eine Antwort auf Ihre Frage gefunden haben. Dies ist für andere Benutzer, die über diese Frage stolpern könnten. Hier ist ein möglicher Weg, dies zu erreichen. Script Task kann verwendet werden, um die Liste der Dateien zu finden, die in einem FTP-Ordnerpfad für ein bestimmtes Muster (z. B. *.txt ). Das nachstehende Beispiel zeigt, wie dies geschehen kann.

Schritt-für-Schritt-Verfahren:

  1. Erstellen Sie im SSIS-Paket eine FTP Connection namens FTP und erstellen auch 5 Variablen wie in Screenshot # gezeigt 1 . Variable RemotePath enthält den FTP-Ordnerpfad; LocalPath enthält den Ordner, in den die Dateien heruntergeladen werden sollen; FilePattern enthält das Dateimuster, um die Liste der Dateien zu finden, die vom FTP-Server heruntergeladen werden sollen; FileName wird von der Foreach loop container aber um Fehler bei der Entwicklung von FTP-Aufgaben zu vermeiden, kann sie mit folgenden Werten gefüllt werden / oder die DelayValidation Eigenschaft des FTP-Tasks kann festgelegt werden auf Wahr .

  2. Platzieren Sie auf dem SSIS-Paket eine Script Task , Foreach Loop container y FTP Task innerhalb der Foreach Loop container wie in den Bildschirmfotos gezeigt # 2 .

  3. Ersetzen Sie die Main() Methode innerhalb der Script Task mit dem Code unter dem Skript Aufgabencode Abschnitt. Der Skript-Task füllt die Variable ListOfFiles mit der Sammlung von Dateien, die einem bestimmten Muster entsprechen. In diesem Beispiel wird zunächst das Muster *.txt verwendet, das keine Ergebnisse liefert, und später das Muster *.xls, das nur wenigen Dateien auf dem FTP-Server entspricht.

  4. Konfigurieren Sie die Foreach Loop container wie in den Bildschirmfotos gezeigt # 3 und 4 . Diese Aufgabe durchläuft in einer Schleife die Variable **ListOfFiles*. Wenn keine Dateien vorhanden sind, wird die FTP-Aufgabe innerhalb des Schleifencontainers nicht ausgeführt. Sind Dateien vorhanden, wird die FTP-Aufgabe innerhalb des Schleifencontainers für die Anzahl der auf dem FTP-Server gefundenen Dateien ausgeführt.

  5. Konfigurieren Sie die FTP Task wie in den Bildschirmfotos gezeigt # 5 und 6 .

  6. Screenshot # 7 zeigt ein Beispiel für die Ausführung eines Pakets, wenn no passende Dateien für das Muster gefunden werden *.txt .

  7. Screenshot # 8 zeigt den Inhalt des Ordners C:\temp\ vor Ausführung des Pakets.

  8. Screenshot # 9 zeigt die Ausführung eines Beispielpakets, wenn passende Dateien für das Muster gefunden werden *.xls .

  9. Screenshot # 10 zeigt den Inhalt des FTP-Remote-Pfads an /Practice/Directory_New .

  10. Screenshot # 11 zeigt den Inhalt des Ordners C:\temp\ nach Ausführung des Pakets.

  11. Screenshot # 12 zeigt das Versagen des Pakets, wenn es mit falschen Entfernter Pfad .

  12. Screenshot # 13 zeigt die Fehlermeldung im Zusammenhang mit dem Paketfehler an.

Ich hoffe, das hilft.

Skriptaufgaben-Code:

C# Code, der verwendet werden kann in SSIS 2008 and above .

Fügen Sie die using Anweisung using System.Text.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, der verwendet werden kann in SSIS 2005 and above .

Fügen Sie die Imports Anweisung Importiert System.Text.ReguläreAusdrücke

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

Screenshot #1:

1

Bildschirmfoto #2:

2

Screenshot #3:

3

Bildschirmfoto #4:

4

Bildschirmfoto #5:

5

Bildschirmfoto #6:

6

Bildschirmfoto #7:

7

Bildschirmfoto #8:

8

Bildschirmfoto #9:

9

Bildschirmfoto #10:

10

Bildschirmfoto #11:

11

Bildschirmfoto #12:

12

Screenshot #13:

13

5voto

tribe84 Punkte 5022

Ich hatte gerade dieses Problem, nach dem Lesen einige der Antworten hier, nichts wirklich sortiert mein Problem und die Lösungen in hier scheinen verrückt in Bezug auf Komplexität.

Meine FTP-Aufgabe schlug fehl, da ich das Überschreiben von Dateien nicht zuließ. Nehmen wir an, der Auftrag wurde zweimal hintereinander gestartet, der erste Durchlauf ist in Ordnung, da einige Dateien übertragen werden, aber er schlägt fehl, wenn eine lokale Datei bereits vorhanden ist.

Meine Lösung war einfach:

  1. Rechtsklick auf Aufgabe - Eigenschaften
  2. Set ForceExecutionResult = "Erfolg"

3voto

thursdaysgeek Punkte 7508

(

I

I

I

    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()

T

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

T

I \\drive\dir\ *

I

A

1voto

Tom H Punkte 45699

Ich habe keine pauschale Antwort für Sie, aber da noch niemand etwas gepostet hat...

Sie sollten in der Lage sein, eine Variable in einer ActiveX-Skriptaufgabe zu setzen und dann anhand dieser Variable zu entscheiden, ob die FTP-Aufgabe ausgeführt werden soll oder nicht. Es gibt ein Beispiel aquí die mit lokalen Pfaden arbeitet. Hoffentlich können Sie das Konzept anpassen (oder, falls möglich, das FTP-Laufwerk zuordnen und es auf diese Weise tun).

1voto

Todd Hoffert Punkte 11

1) Setzen Sie die FTP-Aufgabeneigenschaft ForceExecutionResult = Success

2) Fügen Sie den folgenden Code zum FTP Task OnError Event Handler hinzu.

    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;
    }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X