18

私は SQL Server 2005 を使用しており、SSIS 内で ftp タスクを作成しています。

ftp で転送するファイルがある場合もあれば、そうでない場合もあります。ファイルがない場合、タスクもパッケージも失敗したくありません。ftp タスクから次の「完了」に向かう矢印を変更したので、パッケージが実行されます。エラーの許容数を 4 に変更しました (4 つの ftp タスクがあり、4 つのディレクトリのいずれにもファイルがある場合とない場合があるため)。

しかし、エージェントのジョブからパッケージを実行すると、ジョブが失敗としてマークされます。これは 15 分ごとに実行されるため、ジョブ履歴に赤い x がたくさん表示されるのは望ましくありません。これにより、実際に問題が発生したときに問題が見えなくなります。

ftp へのファイルが見つからなくても失敗しないように、ftp タスクでプロパティを設定するにはどうすればよいですか? 私が使用している操作は「ファイルの送信」です。

ここにいくつかの詳細情報があります。ファイルは、ftp 以外ではアクセスできないサーバー上にあります。また、事前にファイル名がわかりません。ユーザーは、好きなように呼び出すことができます。したがって、特定のファイルをチェックすることはできません。また、まったくチェックできないと思います。ftp 接続とその接続に基づくタスクを使用する場合を除きます。ファイルはリモート サーバー上にあり、それらを自分のサーバーにコピーして、そのリモート サーバーから取得したいと考えています。

スクリプト タスクでコマンド レベルの ftp をシェルできます。おそらく、それは ftp タスクの代わりに使用する必要があるものです。(スクリプト タスクから呼び出されるパラメーター ファイルを使用して、ftp コマンド ラインを使用するように変更しました。取得するファイルがない場合でもエラーは発生しません。この解決策はうまくいくと思います。つまり、プレーン テキスト ファイルに接続情報を含める必要はなく、より安全な場所にある構成ファイルに保存できます)。

4

12 に答える 12

14

ご質問に対する回答が見つかりました。これは、この質問に出くわす可能性のある他のユーザー向けです。これを実現するための 1 つの方法を次に示します。Script Task特定のパターン (たとえば*.txt) の FTP フォルダー パスに存在するファイルのリストを検索するために使用できます。以下の例は、これを行う方法を示しています。

段階的なプロセス:

  1. SSIS パッケージで、FTP Connection名前付きFTPを作成し、スクリーンショット # 1に示すように5 つの変数も作成します。変数には FTP フォルダー パスが含まれます。ファイルがダウンロードされるフォルダーが含まれます。FTP サーバーからダウンロードするファイルのリストを見つけるためのファイル パターンが含まれています。によって入力されますが、FTP タスクの設計時のエラーを回避するために、/またはFTP タスクのプロパティをTrueに設定することで入力できます。RemotePathLocalPathFilePatternFileNameForeach loop containerDelayValidation

  2. SSIS パッケージで、スクリーンショット # 2Script Taskに示すように、Foreach Loop containerと をFTP Task配置します。Foreach Loop container

  3. Main()内のメソッドを、[スクリプト タスク コード]セクションScript Taskのコードに置き換えます。スクリプト タスクは、変数ListOfFilesに、特定のパターンに一致するファイルのコレクションを設定します。この例では、最初にパターン *.txt を使用します。これは結果を生成せず、その後パターン *.xls を使用します。これは FTP サーバー上のほとんどのファイルに一致しません。

  4. Foreach Loop containerスクリーンショット # 3と # 4に示すように構成します。このタスクは、変数 **ListOfFiles* をループします。ファイルがない場合、ループ コンテナー内の FTP タスクは実行されません。ファイルがある場合、ループ コンテナー内の FTP タスクは、FTP サーバーで見つかったファイルの数のタスクに対して実行されます。

  5. FTP Taskスクリーンショット # 5と # 6に示すように構成します。

  6. スクリーンショット7は、パターンに一致するファイルが見つからない場合のサンプル パッケージの実行を示しています*.txt

  7. スクリーンショット # 8は、パッケージの実行C:\temp\ のフォルダーの内容を示しています。

  8. スクリーンショット9は、パターンに一致するファイルが見つかった場合のサンプル パッケージの実行を示しています*.xls

  9. スクリーンショット # 10は、FTP リモート パスの内容を示しています/Practice/Directory_New

  10. スクリーンショット # 11は、パッケージの実行C:\temp\ のフォルダーの内容を示しています。

  11. スクリーンショット # 12は、誤ったリモート パスが指定された場合のパッケージの失敗を示しています。

  12. スクリーンショット # 13は、パッケージの失敗に関連するエラー メッセージを示しています。

それが役立つことを願っています。

スクリプト タスク コード:

で使用できるC#SSIS 2008 and aboveコード。

System.Text.RegularExpressions を使用しusingてステートメントを含めます。

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

で使用できるVBSSIS 2005 and aboveコード。

Imports System.Text.RegularExpressionsImportsステートメントを含めます。

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

スクリーンショット #1:

1

スクリーンショット #2:

2

スクリーンショット #3:

3

スクリーンショット #4:

4

スクリーンショット #5:

5

スクリーンショット #6:

6

スクリーンショット #7:

7

スクリーンショット #8:

8

スクリーンショット #9:

9

スクリーンショット #10:

10

スクリーンショット #11:

11

スクリーンショット #12:

12

スクリーンショット #13:

13

于 2011-07-16T07:14:00.050 に答える
14

SSIS パッケージでタスク エラーを正常に処理する方法について説明しているこのリンクを確認してください。

私はほとんど同じ問題を抱えていましたが、ファイルを取得していました。FTP サーバーでファイルが見つからないときにパッケージが失敗しないようにしたかったのです。上記のリンクは、エラーが発生してパッケージが失敗するのを防ぎます。FailPackageOnError=false を実行する必要があると思ったことはありますか? :-S

これであなたも解決することを願っています!

于 2008-11-20T18:08:26.520 に答える
5

ここでいくつかの返信を読んだ後、私はこの問題を抱えていましたが、私の問題を実際に整理したものは何もなく、ここの解決策は複雑さの点で正気ではないようです.

ファイルの上書きを許可しなかったため、FTP タスクが失敗していました。たとえば、ジョブが 2 回続けて開始されたとします。最初のパスは問題ありません。一部のファイルは転送されますが、ローカル ファイルが既に存在する場合は失敗します。

私の解決策は簡単でした:

  1. 右クリック タスク - プロパティ
  2. ForceExecutionResult = "成功" を設定します
于 2015-10-16T13:37:48.003 に答える
3

(私は自分の答えを受け入れることはできませんが、これは私にとってうまくいった解決策でした。)

最善の解決策ではないかもしれませんが、これでうまくいきます。

私はスクリプト タスクを使用しており、ftp 接続情報、およびソース ディレクトリと宛先ディレクトリ用の変数が多数あります。(これが実行されているサーバーを変更するため、構成パッケージで変更する方が簡単です。)

その場でテキスト ファイルを作成し、それに ftp コマンドを書き込みます。

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

次に、実際に閉じるのに十分な時間を与えた後、ftp コマンドを実行するプロセスを開始します。

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

次に、ftp プロセスが実行されるまでしばらく待ってから、一時的な ftp ファイル (接続情報が含まれています!) を削除します。

ファイルがソース ディレクトリに存在しない場合 (変数が \\drive\dir\*.* マッピングを持っている場合)、エラーは発生しません。他のエラーが発生した場合でも、タスクは正常に失敗します。

私はSSISを初めて使用しますが、これはおかしなことかもしれません。しかし、それは今のところ機能します。私は最善の方法を求めたと思いますが、これがそれであると主張するつもりはありません。

指摘したように、ファイルの名前を知る方法はなく、そこにファイルが存在するかどうかさえもわかりません。あるなら、手に入れたいです。

于 2008-10-02T23:16:09.013 に答える
1

パッケージ化された回答はありませんが、まだ誰も投稿していないので...

ActiveXスクリプトタスクで変数を設定し、それを使用してFTPタスクを実行するかどうかを決定できるはずです。ローカルパスで機能する例がここにあります。うまくいけば、概念を適応させることができます(または、可能であれば、FTPドライブをマップしてそのように実行します)。

于 2008-09-26T18:22:08.333 に答える
0

これは、FTPロジックを手動で書き直すことなく、組み込みのものを使用して、私のために機能している別のソリューションです。

1)FTP_Errorという名前の変数をパッケージに作成します

2)FTPタスクをクリックし、[イベントハンドラー]タブをクリックします

3)ページ内をクリックして、「FTP Task /OnError」のイベントハンドラーを作成します。これは、FTPに問題がある場合に発生します。

4)ツールボックスから、スクリプトタスクアイテムをドラッグし、ダブルクリックして開きます。

5)最初のポップアップで、ReadOnlyVariables-System :: ErrorCode、System::ErrorDescriptionを追加します

6)最初のポップアップで、ReadWriteVariables-User::FTP_Error変数を追加します

7)スクリプトの編集

8)スクリプトで、FTP_Error変数を設定して、上記のReadOnlyVariablesを保持します。

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

9)スクリプトを保存して閉じます

10)「OK」を押してタスクをスクリプト化します

11)「制御フロー」タブに戻ります

12)FTPタスクから、OnErrorは新しいスクリプトタスクに移動し、それを編集します

13)ReadOnlyVariables:以前のUser ::FTP_Error

14)これで、FTPにファイルが見つからない場合、エラーコードは-1073573501になります(エラーコードの参照リストはここにあります:http://msdn.microsoft.com/en-us/library/ms345164.aspx)。

15)スクリプトに、必要な処理を実行するロジックを配置します。「ファイルが見つかりません」というコードが見つかった場合は、タスクが成功したと言うかもしれません。そうでない場合、タスクは失敗しました。そして、あなたの通常の流れはあなたが望むようにこれを扱うことができます:

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

そしてそこから、Succeeded / Failedフローは、それを使ってやりたいことを実行します。

于 2012-02-20T15:20:13.003 に答える
0

失敗した場合は、何もしない別のタスク、つまりtrueを返すだけのスクリプトにリダイレクトできます。

これを行うには、新しいスクリプトタスクを追加し、FTPタスクを強調表示すると、2つ目の緑色のコネクタが表示され、これをスクリプトタスクにドラッグして、ダブルクリックします。[値]ドロップダウンで[失敗]を選択します。明らかに、ジョブ履歴に正しく表示するには、このスクリプトタスクの実際の失敗を処理する必要があります。

于 2008-10-02T14:00:48.223 に答える
0

ああ、OK-説明してくれてありがとう。FTPタスクはフォルダリストを返すことができないため、最初に述べたようにForEachを使用することはできません-これは、X個のファイルをリモートソースにアップロードする場合にのみ機能します。

X量のファイルをダウンロードするには、2つの方法があります。スクリプトタスクで.Netで完全に実行するか、.Netスクリプトタスク内からファイル名をArrayListに入力してから、ArrayList上でForEachを実行します。 、ファイル名を変数に渡し、標準のFTPタスクでその変数名をダウンロードします。

適したコード例:http://forums.microsoft.com/msdn/ShowPost.aspx?PostID = 2472491&SiteID = 1

したがって、上記では、FileNames()を取得し、そこからArrayListを設定し、次にArrayListをDts.VariablesのObjectタイプ変数に割り当て、次にForEachを次のようなコードを使用してそのObject(ArrayList)変数に割り当てます。 ://www.sqlservercentral.com/articles/SSIS/64014/

于 2008-10-02T14:19:39.457 に答える
0

アップロードするファイルを反復処理する ForEach コンテナーに入れます。ファイルも FTP も障害もありません。

于 2008-09-26T20:38:54.917 に答える
0

別の方法は、このFTP ファイル列挙子を使用することです ここに画像の説明を入力

于 2012-07-18T07:28:16.543 に答える