ftp転送時のファイルの競合回避について への返答
投稿で使用できる特殊コードの説明。(別タブで開きます。)
以下の返答は逆順(新しい順)に並んでいます。
投稿者 るきお  (社会人)
投稿日時
2012/6/2 19:03:09
競合エラーとはなんでしょうか?
VBでエラーが発生しているのでしたら具体的な情報をお願いします。
>ファイルのアクセスが競合エラーになります
>時々処理が帰ってこなくなります(ハング)エラーは出ません
>サーバ側では、abortingのエラーになります
状況がよくわかりません…。
知見のある人が読んだだけで状況を理解して回答してくれればよいのですが、
そうでない場合FTPは試すのが面倒なのでコピー&貼り付けだけで実際に動かしてエラーが再現できるものを載せると良いと思います。
(FTPサーバーだけは各自設定する必要がありますが)
VBでエラーが発生しているのでしたら具体的な情報をお願いします。
>ファイルのアクセスが競合エラーになります
>時々処理が帰ってこなくなります(ハング)エラーは出ません
>サーバ側では、abortingのエラーになります
状況がよくわかりません…。
知見のある人が読んだだけで状況を理解して回答してくれればよいのですが、
そうでない場合FTPは試すのが面倒なのでコピー&貼り付けだけで実際に動かしてエラーが再現できるものを載せると良いと思います。
(FTPサーバーだけは各自設定する必要がありますが)
投稿者 nin  (社会人)
投稿日時
2012/6/2 18:24:51
毎度お世話になります
ftpサーバから、10秒おきにデータをgetして、内容を読み出す部分を作成しておりますが、周期が早すぎるのか、ファイルのアクセスが競合エラーになります
パターン1
'FtpWebRequestの作成
Dim ftpReq As System.Net.FtpWebRequest = _
CType(System.Net.WebRequest.Create(u), System.Net.FtpWebRequest)
'ログインユーザー名とパスワードを設定
ftpReq.Credentials = New System.Net.NetworkCredential(UserName, UserPass)
'MethodにWebRequestMethods.Ftp.DownloadFile("RETR")を設定
ftpReq.Method = System.Net.WebRequestMethods.Ftp.DownloadFile
'要求の完了後に接続を閉じる
ftpReq.KeepAlive = False
'ASCIIモードで転送する
ftpReq.UseBinary = False
'PASSIVEモードを無効にする
ftpReq.UsePassive = False
'FtpWebResponseを取得
Dim ftpRes As System.Net.FtpWebResponse = _
CType(ftpReq.GetResponse(), System.Net.FtpWebResponse)
'ファイルをダウンロードするためのStreamを取得
Dim resStrm As System.IO.Stream = ftpRes.GetResponseStream()
'ダウンロードしたファイルを書き込むためのFileStreamを作成
Dim fs As New System.IO.FileStream( _
downFile, System.IO.FileMode.Create, System.IO.FileAccess.Write)
'ダウンロードしたデータを書き込む
Dim buffer(1023) As Byte
While True
Dim readSize As Integer = resStrm.Read(buffer, 0, buffer.Length)
If readSize = 0 Then
Exit While
End If
fs.Write(buffer, 0, readSize)
End While
fs.Close()
resStrm.Close()
ftpRes.Close()
上記処理の後
'データを配列Ataiに読み込む
Dim Reader As New IO.StreamReader(Application.StartupPath + "\ichi.csv", _
System.Text.Encoding.GetEncoding("Shift-JIS"))
・
・
・
IO.StreamReaderで、読み出しています
時々処理が帰ってこなくなります(ハング)エラーは出ません
サーバ側では、abortingのエラーになります
20秒周期にしてみましたが、結果同じでした
切り分けの為、ダウンロードのファイルと、読出ファイルを別のファイルで実行しましたが
結果同じでした。PCに書き込まないように書込部をコメントアウトしましたが、同じでした
パターン2
昔ながらの、SHELLコマンドで、FTPコマンドを使ってファイルをDLしたところ、時々
IO.StreamReader処理で、競合エラーで停止します
SHELLの実行で、処理が終了するまで、次の処理にいかないように、変更してみましたが
結果同じでした
Dim procId As Long 'プロセスID
Dim hProc As Object 'プロセスハンドル
Dim strPNAME As String
strPNAME = """" + Application.StartupPath + "\ftpftp.txt" + """"
procId = Shell("ftp -s:" + strPNAME, vbHide)
hProc = OpenProcess(PROCESS_ALL_ACCESS, False, procId) 'プロセスハンドルを取得します。
If hProc > 0 Then 'プロセスハンドルを取得できた場合
Call WaitForSingleObject(hProc, INFINITE) 'プロセスがシグナル状態になるまで待ちます。
CloseHandle(hProc) 'プロセスハンドルを解放します。
切り分けの為、ダウンロードのファイルと、読出ファイルを別のファイルしたところ、競合しませんでした
読出中に、FTPコマンドで書き込もうとして競合しているように見えます(FTPがプロセスで残る)
なにか、いい解決方法ないでしょうか?
試しに、Reader中でも書込みを許可してみたいのですが、記述方法が判りません
長々と申し訳ありませんが、よろしくお願いします
ftpサーバから、10秒おきにデータをgetして、内容を読み出す部分を作成しておりますが、周期が早すぎるのか、ファイルのアクセスが競合エラーになります
パターン1
'FtpWebRequestの作成
Dim ftpReq As System.Net.FtpWebRequest = _
CType(System.Net.WebRequest.Create(u), System.Net.FtpWebRequest)
'ログインユーザー名とパスワードを設定
ftpReq.Credentials = New System.Net.NetworkCredential(UserName, UserPass)
'MethodにWebRequestMethods.Ftp.DownloadFile("RETR")を設定
ftpReq.Method = System.Net.WebRequestMethods.Ftp.DownloadFile
'要求の完了後に接続を閉じる
ftpReq.KeepAlive = False
'ASCIIモードで転送する
ftpReq.UseBinary = False
'PASSIVEモードを無効にする
ftpReq.UsePassive = False
'FtpWebResponseを取得
Dim ftpRes As System.Net.FtpWebResponse = _
CType(ftpReq.GetResponse(), System.Net.FtpWebResponse)
'ファイルをダウンロードするためのStreamを取得
Dim resStrm As System.IO.Stream = ftpRes.GetResponseStream()
'ダウンロードしたファイルを書き込むためのFileStreamを作成
Dim fs As New System.IO.FileStream( _
downFile, System.IO.FileMode.Create, System.IO.FileAccess.Write)
'ダウンロードしたデータを書き込む
Dim buffer(1023) As Byte
While True
Dim readSize As Integer = resStrm.Read(buffer, 0, buffer.Length)
If readSize = 0 Then
Exit While
End If
fs.Write(buffer, 0, readSize)
End While
fs.Close()
resStrm.Close()
ftpRes.Close()
上記処理の後
'データを配列Ataiに読み込む
Dim Reader As New IO.StreamReader(Application.StartupPath + "\ichi.csv", _
System.Text.Encoding.GetEncoding("Shift-JIS"))
・
・
・
IO.StreamReaderで、読み出しています
時々処理が帰ってこなくなります(ハング)エラーは出ません
サーバ側では、abortingのエラーになります
20秒周期にしてみましたが、結果同じでした
切り分けの為、ダウンロードのファイルと、読出ファイルを別のファイルで実行しましたが
結果同じでした。PCに書き込まないように書込部をコメントアウトしましたが、同じでした
パターン2
昔ながらの、SHELLコマンドで、FTPコマンドを使ってファイルをDLしたところ、時々
IO.StreamReader処理で、競合エラーで停止します
SHELLの実行で、処理が終了するまで、次の処理にいかないように、変更してみましたが
結果同じでした
Dim procId As Long 'プロセスID
Dim hProc As Object 'プロセスハンドル
Dim strPNAME As String
strPNAME = """" + Application.StartupPath + "\ftpftp.txt" + """"
procId = Shell("ftp -s:" + strPNAME, vbHide)
hProc = OpenProcess(PROCESS_ALL_ACCESS, False, procId) 'プロセスハンドルを取得します。
If hProc > 0 Then 'プロセスハンドルを取得できた場合
Call WaitForSingleObject(hProc, INFINITE) 'プロセスがシグナル状態になるまで待ちます。
CloseHandle(hProc) 'プロセスハンドルを解放します。
切り分けの為、ダウンロードのファイルと、読出ファイルを別のファイルしたところ、競合しませんでした
読出中に、FTPコマンドで書き込もうとして競合しているように見えます(FTPがプロセスで残る)
なにか、いい解決方法ないでしょうか?
試しに、Reader中でも書込みを許可してみたいのですが、記述方法が判りません
長々と申し訳ありませんが、よろしくお願いします
返信ありがとうございます
なんとか、解決できそうです
パターン2は、SHELL でftpコマンドを実行した場合、処理に1秒以上要しており、ダウンロード後にファイルをオープンしようとしてエラーになっていました。処理の終了をうまく判断できないようです
エラー処理で、ファイルの排他が外れるのを待つ処理で対応しようと思ったのですが、1秒単位で描画しているのと、ftpサーバのファイル更新処理との同期もあり、難しくて断念しました。
FtpWebRequestの未応答になる状態は、ReadWriteTimeoutの設定で、1秒以内にタイムアウトさせることで、エラーが出なくなりました 処理的には、こちらのほうが断然早いです
お騒がせして、申し訳ありません。