C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

Ftpのアップロード /初心者 (24/05/22(Wed) 17:28) #103121
Re[1]: Ftpのアップロード /魔界の仮面弁士 (24/05/22(Wed) 19:19) #103122
│└ Re[2]: Ftpのアップロード /魔界の仮面弁士 (24/05/23(Thu) 09:21) #103123
Re[1]: Ftpのアップロード /魔界の仮面弁士 (24/05/23(Thu) 09:39) #103124
  └ Re[2]: Ftpのアップロード /初心者 (24/05/28(Tue) 13:58) #103141
    └ Re[3]: Ftpのアップロード /KOZ (24/06/03(Mon) 10:42) #103170
      └ Re[4]: Ftpのアップロード /初心者 (24/06/05(Wed) 17:35) #103171 解決済み


親記事 / ▼[ 103122 ] ▼[ 103124 ]
■103121 / 親階層)  Ftpのアップロード
□投稿者/ 初心者 (7回)-(2024/05/22(Wed) 17:28:06)

分類:[.NET 全般] 

VB.netは初心者ですが、いま、Dobon.netサイトのコードを参考にFTPのアップロードを作成しています。
問題は、 下記の「<-この行でタイムアウトになる」のところで止まり安定していません。
正常だったり、エラーだったりします。
設定では、
'要求の完了後に接続を閉じる
ftpReq.KeepAlive = False
'ASCIIモードで転送する
ftpReq.UseBinary = False
'PASVモードを無効にする
ftpReq.UsePassive = False  Trueに変えたりして安定して動作するところをさがしてるがうまくいきません
因みに、Ftpは、FC2のFTPで、PASVモードらしいのですが、
大雑把な説明で申し訳ないのですがどなたかわかる方、お教えください、宜しくお願います

以下の行でエラーとなります
Dim reqStrm As System.IO.Stream = ftpReq.GetRequestStream()


サンプルコード(upFile 、uの値は、実データで行っています)
'アップロードするファイル
Dim upFile As String = "C:\test.txt"
'アップロード先のURI
Dim u As New Uri("ftp://localhost/test.txt")

'FtpWebRequestの作成
Dim ftpReq As System.Net.FtpWebRequest = _
CType(System.Net.WebRequest.Create(u), System.Net.FtpWebRequest)
'ログインユーザー名とパスワードを設定
ftpReq.Credentials = New System.Net.NetworkCredential("username", "password")
'MethodにWebRequestMethods.Ftp.UploadFile("STOR")を設定
ftpReq.Method = System.Net.WebRequestMethods.Ftp.UploadFile
'要求の完了後に接続を閉じる
ftpReq.KeepAlive = False
'ASCIIモードで転送する
ftpReq.UseBinary = False
'PASVモードを無効にする
ftpReq.UsePassive = False

'ファイルをアップロードするためのStreamを取得
Dim reqStrm As System.IO.Stream = ftpReq.GetRequestStream() <-この行でタイムアウトになる
'アップロードするファイルを開く
Dim fs As New System.IO.FileStream( _
upFile, System.IO.FileMode.Open, System.IO.FileAccess.Read)
'アップロードStreamに書き込む
Dim buffer(1023) As Byte
While True
Dim readSize As Integer = fs.Read(buffer, 0, buffer.Length)
If readSize = 0 Then
Exit While
End If
reqStrm.Write(buffer, 0, readSize)
End While
fs.Close()
reqStrm.Close()

'FtpWebResponseを取得
Dim ftpRes As System.Net.FtpWebResponse = _
CType(ftpReq.GetResponse(), System.Net.FtpWebResponse)
'FTPサーバーから送信されたステータスを表示
Console.WriteLine("{0}: {1}", ftpRes.StatusCode, ftpRes.StatusDescription)
'閉じる
ftpRes.Close()
[ □ Tree ] 返信 編集キー/

▲[ 103121 ] / ▼[ 103123 ]
■103122 / 1階層)  Re[1]: Ftpのアップロード
□投稿者/ 魔界の仮面弁士 (3775回)-(2024/05/22(Wed) 19:19:14)
2024/05/22(Wed) 19:27:07 編集(投稿者)

No103121 (初心者 さん) に返信
> VB.netは初心者ですが、いま、Dobon.netサイトのコードを参考にFTPのアップロードを作成しています。
あちらの掲示板では無く、wankuma での質問なんですね。まぁ、こちらへの投稿でも問題は無いです。
現時点では、原因がコードなのかサーバーなのかライブラリなのかも分からないですしね。


ひとまず Windows 標準の Explorer や、
その他の FTP クライアントツール(WinSCP とか)から
接続する分には、特に問題が出ていない感じでしょうか?

FtpWebRequest には幾つかの問題があり、新規開発での利用は推奨されていないそうです。

FTP クライアント ツールでの通信では問題がでていないのであれば、方針転換で
FtpWebRequest は使わず、別のライブラリ(FluentFTP など)に切り替えるのは如何でしょうか。
https://stackoverflow.com/questions/1371964/free-ftp-library


> 因みに、Ftpは、FC2のFTPで、PASVモードらしいのですが、
> 大雑把な説明で申し訳ないのですがどなたかわかる方、お教えください、宜しくお願います
FC2 の契約を結んでいないので、細かい事は分かりませんが、
サーバー側でアクセスログをとることは可能でしょうか?
https://help.fc2.com/lite/manual/group229/3632

サーバー側のログが得られれば、そもそもリクエストがサーバーに届いていないのか、
それとも届いた上で、サーバーからのレスポンスをクライアントが受け取れていないのかを
判断する手掛かりになるかもしれません。


> 問題は、 下記の「<-この行でタイムアウトになる」のところで止まり安定していません。
> 正常だったり、エラーだったりします。
正常だった場合とエラーだった場合で、ログの差異を確認してみるとか。


> 'PASVモードを無効にする
Windows Firewall あるいはルーター側で塞がれているポートは無いでしょうか。
データ転送に使われるポートの割り当て範囲も確認してみてください。
https://yurakawa.hatenablog.jp/entry/2017/09/04/202518


セキュリティソフトが原因で通信がブロックされ、タイムアウト扱いになることはしばしばありますので、お使いのセキュリティソフトに何か通知が来ていないかも確認してみた方が良いかも。
[ 親 103121 / □ Tree ] 返信 編集キー/

▲[ 103122 ] / 返信無し
■103123 / 2階層)  Re[2]: Ftpのアップロード
□投稿者/ 魔界の仮面弁士 (3776回)-(2024/05/23(Thu) 09:21:00)
No103122 (魔界の仮面弁士 さん) に返信
> サーバー側のログが得られれば、そもそもリクエストがサーバーに届いていないのか、
> それとも届いた上で、サーバーからのレスポンスをクライアントが受け取れていないのかを
> 判断する手掛かりになるかもしれません。

FTP のログを読み取るには、プロトコルのメッセージに関する幾許かの知識が要求されますが、
サーバーログと併せて、クライアント側のログも判断材料になるかもしれません。
たとえば FtpWebRequest であれば、app.config にてネットワークトレースを有効化し、
通信ログを、ファイル/イベントログ/コンソール等に出力させるようにします。
https://learn.microsoft.com/ja-jp/dotnet/framework/network-programming/network-tracing?WT.mc_id=DT-MVP-8907


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <sources>
      <source name="System.Net" tracemode="protocolonly" maxdatasize="1024">
        <listeners>
          <add name="System.Net"/>
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="System.Net" value="Information"/>
    </switches>
    <sharedListeners>
      <add name="System.Net"
        type="System.Diagnostics.TextWriterTraceListener"
        initializeData="network.log"
      />
    </sharedListeners>
    <trace autoflush="true"/>
  </system.diagnostics>
</configuration>

[ 親 103121 / □ Tree ] 返信 編集キー/

▲[ 103121 ] / ▼[ 103141 ]
■103124 / 1階層)  Re[1]: Ftpのアップロード
□投稿者/ 魔界の仮面弁士 (3777回)-(2024/05/23(Thu) 09:39:07)
No103121 (初心者 さん) に返信
> 因みに、Ftpは、FC2のFTPで、PASVモードらしいのですが、

System.Net.FtpWebRequest を使って、FC2 のサイトに
ファイルをアップロードする記事を見つけました。
https://scorpion140309.blog.fc2.com/blog-entry-205.html


ftp://example.com/dir/file.txt では失敗したので、
ftp://example.com//dir/file.txt だと成功したとか、
ftp://example.com/var/www/html/dir/file.txt が必要なケースがあるとか、
アスキーモードの代わりにバイナリモードでの転送を試したら安定した
といった情報が記載されています。


C# ではありますが、検証用のソースコードも公開されていますね。
https://scorpion140309.github.io/arc/C_Sharp/FTP_test_170629a_src.zip
[ 親 103121 / □ Tree ] 返信 編集キー/

▲[ 103124 ] / ▼[ 103170 ]
■103141 / 2階層)  Re[2]: Ftpのアップロード
□投稿者/ 初心者 (8回)-(2024/05/28(Tue) 13:58:59)
No103124 (魔界の仮面弁士 さん) に返信
魔界の仮面弁士 さん多岐わたり回答・助言ありがとうございます。
色々と試しすぎて、コードにちょっと自身がありませんが、エラーが沢山発生
しましたので、ここから分かることが見つかればと思っています。
おんぶにだっこのようなことになってしまいましたが、さっぱり突破口がありません。
皆さんお忙しいと思いますが宜しくお願います。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
1.個々の回答についての対応
2.FluentFtpのコードを書いてみましたが・・・  
3.FtpWebRequesでの再試み
4.コマンドプロンプトのFtpの結果
5.その他の質問
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

1.個々の回答について
>> VB.netは初心者ですが、いま、Dobon.netサイトのコードを参考にFTPのアップロードを作成しています。
>あちらの掲示板では無く、wankuma での質問なんですね。まぁ、こちらへの投稿でも問題は無いです。
>現時点では、原因がコードなのかサーバーなのかライブラリなのかも分からないですしね。
 →質問はこのサイトしか思いつかなかったので、問題があったならごめんなさい。

>その他の FTP クライアントツール(WinSCP とか)から
>接続する分には、特に問題が出ていない感じでしょうか?
 → FTPツール(FFFTP)では、問題無く動作しています

>FtpWebRequest には幾つかの問題があり、新規開発での利用は推奨されていないそうです。
 →ネットにもそのようなことが書かれていましたので、FluentFTPでコーディングしてみましたが、
 安定した動作がえられませんでした。後述参照

>> 因みに、Ftpは、FC2のFTPで、PASVモードらしいのですが、
>> 大雑把な説明で申し訳ないのですがどなたかわかる方、お教えください、宜しくお願います
>FC2 の契約を結んでいないので、細かい事は分かりませんが、
>サーバー側でアクセスログをとることは可能でしょうか?
>https://help.fc2.com/lite/manual/group229/3632
 →フリーのFc2.comの為、見つけられませんでした。またスキル以上の為、トレースやログ解析は
 皆目検討が付きませんので、ちょっと保留です。

>> 'PASVモードを無効にする
>Windows Firewall あるいはルーター側で塞がれているポートは無いでしょうか。
>データ転送に使われるポートの割り当て範囲も確認してみてください。
>https://yurakawa.hatenablog.jp/entry/2017/09/04/202518
 →スキル以上の為、ちょっと保留です

>セキュリティソフトが原因で通信がブロックされ、タイムアウト扱いになることはしばしばありますので、
>お使いのセキュリティソフトに何か通知が来ていないかも確認してみた方が良いかも。
 →スキル以上の為、ちょっと保留です。この辺の理解があると、解決も近いと思うのですが淋しい

>System.Net.FtpWebRequest を使って、FC2 のサイトに
>ファイルをアップロードする記事を見つけました。
>https://scorpion140309.blog.fc2.com/blog-entry-205.html
>ftp://example.com/dir/file.txt では失敗したので、
>ftp://example.com//dir/file.txt だと成功したとか、
>ftp://example.com/var/www/html/dir/file.txt が必要なケースがあるとか、
>アスキーモードの代わりにバイナリモードでの転送を試したら安定した
>といった情報が記載されています。
 →全て試みましたが、
 Dim ftpReq As System.Net.FtpWebRequest = CType(System.Net.WebRequest.Create(u), System.Net.FtpWebRequest) の行で
 エラーになります。

>C# ではありますが、検証用のソースコードも公開されていますね。
>https://scorpion140309.github.io/arc/C_Sharp/FTP_test_170629a_src.zip
 →C#は勉強不足で、壁が高いでした
 
2.FluentFtpのコードを書いてみましたが・・・
 正常動作する場合もあるのですが、エラーになることが多いです。
 また、PASV等の設定がありませんが無視して良いのか気になります。
 参考のサイトから作成した結果になりますが
 2.1 エラー箇所1でのエラー内容
 例外がスローされました: 'System.TimeoutException' (FluentFTP.dll の中)
 errTimed out trying to connect!
 2.2 エラー箇所2でのエラー内容
 例外がスローされました: 'FluentFTP.Exceptions.FtpException' (FluentFTP.dll の中)
 errError while uploading the file to the server. See InnerException for more info.
 気になるサイトがありました。
 https://atmarkit.itmedia.co.jp/bbs/phpBB/viewtopic.php?topic=39466&forum=7&start=8
 
 以下FluentFtpのコード
  Dim var_Host As String = "Servertest.web.fc2.com"
Dim var_Username As String = "Usertest"
Dim var_Password As String = "Passwordtest"
Dim var_ServerTestDirectory1 As String = "/Log"
Dim var_ServerTestDirectory2 As String = "C:\temp\temp.txt"
Dim var_ServerTestDirectory3 As String = "/Log/temp.txt"
' FTP クライアントの作成
Dim client As New FtpClient(var_Host)
'ログイン認証の指定をしない場合は、"anonymous" が使われる。
client.Credentials = New NetworkCredential(var_Username, var_Password)
Try
' サーバーへの接続を開始
client.Connect()
If client.IsConnected Then
For Each item As FtpListItem In client.GetListing("/Log")   'エラー箇所1
Console.Write(item.FullName & vbCrLf)
Next
If IO.File.Exists(var_ServerTestDirectory2) Then
'MsgBox("Upload")
Dim ftpstatus = client.UploadFile(var_ServerTestDirectory2, 'エラー箇所2
var_ServerTestDirectory3)
MsgBox("OK" & vbCrLf)
End If
End If
Catch ex As Exception
Console.Write("err" & ex.Message)
Finally
' 切断。またね!
client.Disconnect()
'破棄(切断も行う)。
client.Dispose()
MsgBox("Disconnect")
End Try



3.FtpWebRequesでの再試み
 3.1不安定なコード部分
'FtpWebResponseを取得
Dim ftpRes As System.Net.FtpWebResponse = CType(ftpReq.GetResponse(), System.Net.FtpWebResponse)
  【エラー結果】
  例外がスローされました: 'System.Net.WebException' (System.dll の中)
  リモート サーバーがエラーを返しました: 227 Entering Passive Mode (xxx,xxx,xx,xx,xxx,x).
 ・気になるサイトの記事がありました。
  https://atmarkit.itmedia.co.jp/bbs/phpBB/viewtopic.php?topic=39466&forum=7&start=8
  引用
  「ループ開始時にNetworkCredentialインスタンスを一つ作成し、
  それをすべてのFTPWebRequestで共有するようにするのが正しい方法です。」
  →実行したところ問題が解決したらしいですが、何処をどうしたのかが全くわかりません。
   認証の問題と感じたのですが具体的に説明をいただければ幸いです。
  
 以下FtpWebRequesのコード(抜粋)
'FtpWebRequestの作成
Dim ftpReq As System.Net.FtpWebRequest = CType(System.Net.WebRequest.Create(u), System.Net.FtpWebRequest)
'ログインユーザー名とパスワードを設定
ftpReq.Credentials = New System.Net.NetworkCredential(var_Username, var_Password)
'MethodにWebRequestMethods.Ftp.DownloadFile("RETR")を設定
ftpReq.Method = System.Net.WebRequestMethods.Ftp.DownloadFile
'要求の完了後に接続を閉じる
ftpReq.KeepAlive = False
'ASCIIモードで転送する
ftpReq.UseBinary = False
'PASSIVEモードを無効にする
ftpReq.UsePassive = True

'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(
upFile, 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()

'FTPサーバーから送信されたステータスを表示
Console.WriteLine("{0}: {1}", ftpRes.StatusCode, ftpRes.StatusDescription)
'閉じる
ftpRes.Close()
MsgBox("OK")
Err:
Console.Write(Err.Description)
End Sub


4.FTPの操作内容
 4.1 dirコマンド実行でタイムアウトになる
   こんな現象からわかることはありますか?

以下コマンド実行例
C:\Windows\system32>ftp
  :
ログイン部分は割愛
  :
230 User acadheart logged in
ftp> lcd C:\temp
ローカル ディレクトリは現在 C:\temp です。
ftp> !dir
ドライブ C のボリューム ラベルは Windows です
ボリューム シリアル番号は E657-6947 です

C:\temp のディレクトリ

2024/05/27 17:11 <DIR> .
2024/05/27 17:11 <DIR> ..
0 個のファイル 0 バイト
2 個のディレクトリ 230,915,448,832 バイトの空き領域
ftp> dir
200 PORT command successful     
425 Unable to build data connection: Connection timed out  'タイムアウトされた リストが表示されない

5.その他の質問
 実行形式の希望は、EXEファイルのみで動作することなのですが、Fluentftpを使用したの場合は、
 Fluentftp.dllとセットとなると思います。EXEに組み込む事は可能なのでしょうか?
[ 親 103121 / □ Tree ] 返信 編集キー/

▲[ 103141 ] / ▼[ 103171 ]
■103170 / 3階層)  Re[3]: Ftpのアップロード
□投稿者/ KOZ (459回)-(2024/06/03(Mon) 10:42:12)
No103141 (初心者 さん) に返信
> 2.FluentFtpのコードを書いてみましたが・・・
>  正常動作する場合もあるのですが、エラーになることが多いです。
>  また、PASV等の設定がありませんが無視して良いのか気になります。

PASV は ftp サイト側、非PASV はクライアント側でデータコネクションを Listen します。
なので、クライアント側のポートがなんらかの制限を受けているのでしょう。

PASV で接続する設定は

Dim config As New FtpConfig() With {.DataConnectionType = FtpDataConnectionType.PASV}
Dim client As New FtpClient("ホスト名", config:=config)

こんな感じです
[ 親 103121 / □ Tree ] 返信 編集キー/

▲[ 103170 ] / 返信無し
■103171 / 4階層)  Re[4]: Ftpのアップロード
□投稿者/ 初心者 (9回)-(2024/06/05(Wed) 17:35:18)
No103170 (KOZ さん) に返信
> ■No103141 (初心者 さん) に返信
>>2.FluentFtpのコードを書いてみましたが・・・
>> 正常動作する場合もあるのですが、エラーになることが多いです。
>> また、PASV等の設定がありませんが無視して良いのか気になります。
>
> PASV は ftp サイト側、非PASV はクライアント側でデータコネクションを Listen します。
> なので、クライアント側のポートがなんらかの制限を受けているのでしょう。
>
> PASV で接続する設定は
>
> Dim config As New FtpConfig() With {.DataConnectionType = FtpDataConnectionType.PASV}
> Dim client As New FtpClient("ホスト名", config:=config)
>
> こんな感じです
KOZ さん 返信ありがとうございます。
早速、試してみたら、10回程度実行してもエラーにはなりませんでしたので、問題解決です。
魔界の仮面弁士さんの提案や、KOZ さんのご協力に改めて感謝を申し上げます。
心の声(私にや、このコードは検討が付きませんね〜)

解決済み
[ 親 103121 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -