Azureの開発をしていて、BlockBlobをFTPでサーバーへ転送する必要があったので、覚書をして残しておきます。

ZIPファイル化(Azureのストレージ上にあるBLOBをzipして保存する方法)と同様にローカルにあるファイルのように直接転送することが出来ません。
ZIPファイル化と同じように、一度ストリームに読み込む必要があります。

以下サンプルコードです。(今回はFTPS送信のため、証明書のチェックがあります)

using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;namespace WorkerRole1
{
class Class1
{
public void TransferFile_FTP()
{
//FTPサーバーの指定
// ServerNameを指定する
string ServerName = “ftp://hogehoge.com/”;
// FTPのユーザー名
string FtpUsername = “UserName”;
// FTPのパスワード
string FtpPassword = “Password”;
// ユーザー名とパスワードを指定
NetworkCredential cred = new NetworkCredential(FtpUsername, FtpPassword);//Blobコンテナーの指定
// ストレージアカウントの生成(StorageConnectionStringはapp.configに記載、内容はポータルから取得する)
/* <appSettings>
<add key=”StorageConnectionString” value=”DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=account-key” />
</appSettings>
*/
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(StorageConnectionString);
// BLOBクライアントの生成
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// BLOBのコンテナ取得
CloudBlobContainer container = blobClient.GetContainerReference(“コンテナ名'”);
// Blobコンテナーからファイル名を取得する。
// ファイル名を指定して転送する場合には、nullをファイル名(仮想階層込)にする。
// またファイル名は一部のみでもよい。
foreach (IListBlobItem item in container.ListBlobs(null, false))
{
//BlockBlobの場合に転送する。(ここをCloudAppendBlobに返るとAppendBlobも転送できる)
if (item.GetType() == typeof(CloudBlockBlob))
{
//item指定
CloudBlockBlob blob = (CloudBlockBlob)item;
//Ftpサーバーの指定
// ファイル名の指定
// 仮想階層を使用している場合には、仮想階層をReplaceで除く
string FileNames = blob.Name; //blob.Name.Replace(“仮想階層”, “”);
// FtpWebRequestの作成
Uri u = new Uri(ServerName + FileNames);
FtpWebRequest ftpReq = (FtpWebRequest)WebRequest.Create(u);
//ログインユーザー名とパスワードを設定
ftpReq.Credentials = cred;
// Methodには”STOR”を設定
ftpReq.Method = WebRequestMethods.Ftp.UploadFile;
// 接続高速化
ftpReq.Proxy = null;
// 要求の完了後に接続を閉じる
ftpReq.KeepAlive = false;
// ASCIIモードで転送する
ftpReq.UseBinary = false;
// PASSIVEモードを有効にする
ftpReq.UsePassive = true;
// SSL通信設定
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(OnRemoteCertificateValidationCallback);
ftpReq.EnableSsl = true;
// ファイルをアップロードするためのStreamを取得
System.IO.Stream reqStrm = ftpReq.GetRequestStream();
CloudBlob ZipBlob = container.GetBlobReference(blob.Name);
var memoryStream = new MemoryStream();
ZipBlob.DownloadToStream(memoryStream);
// BLOBを一度ストリームに取り込み、サイズを取得する
string text = Encoding.UTF8.GetString(memoryStream.ToArray());
// ファイルを読み込むバイト配列の初期化
long fileByteLength = ZipBlob.Properties.Length;
byte[] fileBytes = new byte[fileByteLength];
// バイト配列に読み込む
ZipBlob.DownloadToByteArray(fileBytes, 0);
//アップロードのためのstreamに書き込み
int fileByteLengths = (int)fileByteLength;
reqStrm.Write(fileBytes, 0, fileByteLengths);
//クローズ
reqStrm.Close();
// FtpWebResponseを取得
FtpWebResponse ftpRes = (FtpWebResponse)ftpReq.GetResponse();
}
}
}
private static bool OnRemoteCertificateValidationCallback(
Object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
//証明の内容をチェック
if (sslPolicyErrors == SslPolicyErrors.None)
{
//SSL証明書に問題なし
return true;
}
else
{
if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) ==
SslPolicyErrors.RemoteCertificateChainErrors)
{
//【SSL証明書】ChainStatusが、空でない配列を返しました
return false;
}
else if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) ==
SslPolicyErrors.RemoteCertificateNameMismatch)
{
//【ERROR】証明書の名前が一致していません
return false;
}
else if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) ==
SslPolicyErrors.RemoteCertificateNotAvailable)
{
//【SSL証明書】証明書が利用できません
return false;
}
else
{
//【SSL証明書】予期しないエラーが発生しました
return false;
}
}
}
}
}