Skip to content

memory stream

KS LIM edited this page Nov 9, 2022 · 6 revisions

Home

ZipArchive.CreateEntry Add new files to an exsting zip archive
ZipArchive.Entries Retrieve all the files from a zip archive
Working Example Download Unzip Zip
lean version Break down the code into separate methods

ZipArchive CreateEntry

home

  1. httpRequest at the frontend
const queries = '&fileValue=' + myList + '&fileName=' + this.routeQuery.equipmentName + '_' + fType
this.$axios
     .get(process.env.API.EQUIPMENT_OTHER_DOWNLOADZIP + '?' + queries)
     .then((response) => {
        document.location.href = response.request.reponseURL
     })  
  1. backend
[HttpGet]
[Route("downloadzip")]
public async Task<ActionResult> GetZipFile(string fileName, string fileName)
{
   byte[] result = this.equipmentCSVLinkService.GetZipFile(fileValue);
   return this.File(result, "application/zip", fileName + ".zip");
}
  1. Download the file from Azure Blob into memory stream and zip them up
static string connectionString = Environment.GetEnvironmentVariable("BACKUP_BLOB_ACCOUNT_KEY");
static string containerName = Environment.GetEnvironmentVariable("BACKUP_BLOB_ACCOUNT_CONTAINER_NAME");
public byte[] GetZipFile(string fileValue)
{
  BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);
  BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);
  var blobs = containerClient.GetBlobs();
  using (MemoryStream ms = new MemoryStream())
  {
    using (ZipArchive archive = new ZipArchive(ms, ZipArchiveMode.Create))
    { 
       foreach (var blob in blobs)
       {
          string[] file = blob.Name.Split('/');
          string[] _fileValue = fileValue.Split(',').ToArray();
          foreach (dynamic f in _fileValue)
          {
             if (f == blob.Name)
             {
                MemoryStream ms2 = new MemoryStream();
                BlobClient blobClient = containerClient.GetBlobClient(blob.Name);
                blobClient.DownloadTo(ms2);
                byte[] content = ms2.ToArray();
                ZipArchiveEntry orderEntry = archive.CreateEntry(file[2]);
                using (BinaryWriter writer  = new BinaryWriter(orderEntry.Open()))
                { 
                   // write the binary data
                   writer.Write(content);
                }
             }  
          }
       }
    }
    return ms.ToArray();
  }
}

ZipArchive Entries

home

  • the following will output the unzipped files into the memorystream
BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);
BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);
var blobs = containerClient.GetBlobs();

using (MemoryStream ms = new MemoryStream())
{
 MemoryStream ms2 = null;
 using (ZipArchive archive = new ZipArchive(ms, ZipArchiveMode.Create))
 {
   foreach (var blob in blobs)
   {
     string[] file = blob.Name.Split('/');
     // コンマ文字列を文字列配列に変換する
     string[] _fileValue = fileValue.Split(',').ToArray();
     foreach (dynamic f in _fileValue)
     {
       if (f == blob.Name)
       {
        // blobファイル保存用メモリストリーム作成してファイルをダウンロードする
        ms2 = new MemoryStream();
        BlobClient blobClient = containerClient.GetBlobClient(blob.Name);
        blobClient.DownloadTo(ms2);
        byte[] content = ms2.ToArray();

        //Stream data = new MemoryStream(); // The original data
        Stream unzippedEntryStream; // Unzipped data from a file in the archive

        ZipArchive archive2 = new ZipArchive(ms2);
        foreach (ZipArchiveEntry entry in archive2.Entries)
        {
          if (entry.FullName.EndsWith(".csv", StringComparison.OrdinalIgnoreCase))
          {
           unzippedEntryStream = entry.Open(); // .Open will return a stream
           /*
           ZipArchiveEntry orderEntry = archive.GetEntry(entry.Name);
           using (StreamWriter writer = new StreamWriter(orderEntry.Open()))
           {
             writer.BaseStream.Seek(0, SeekOrigin.End);
             writer.WriteLine("append line to file");
           }
           orderEntry.LastWriteTime = DateTimeOffset.UtcNow.LocalDateTime;
           */
         }
      }
      /*
      ZipArchiveEntry orderEntry = archive.CreateEntry(file[2]);
      using (BinaryWriter writer = new BinaryWriter(orderEntry.Open()))
      {
       // write the binary data
       writer.Write(content);
      }
      */
     }
    }
   }
  }
  return ms2.ToArray();
}

Working Example

home

[HttpGet]
[Route("downloadzip")]
public async Task<ActionResult> GetZipFile(string fileId, string fileName, string fileType, string yearMonth)
{
 // Blobフォルダー検索パラメータ
            string path = "equipment/cs";
            if (fileType == "history") path = "equipment-history/cs";
            if (fileType == "other") path = "equipment-other/cs";

            byte[] result = await this.equipmentCSVLinkService.GetZipFile(fileId, path);

            // 1データごとの出力時のZipファイル名称設定
            // 例:fileId = 99  and yearMonth= 202209_100,202208_99 then fDate[0] = 202208
            string[] fId = fileId.Split(',').ToArray();
            if(fId.Length == 1)
            {
                string[] fDate = yearMonth.Split(',').ToArray();
                foreach (string d in fDate)
                {
                    string[] fDateId = d.Split('_').ToArray();
                    if (fDateId[1].ToString() == fId[0].ToString())
                    {
                        fileName = fDateId[0].ToString() + "_" + fileName;
                    }
                }
            }
            // Zipファイルをクライアントに返す
            return this.File(result, MediaTypeNames.Application.Zip, fileName + ".zip");           
}
namespace IotRmsWeb.Services.MaintenanceSetting
{
    /// <summary>
    /// その他タブ画面サービスクラス
    /// </summary>
    public class MaintenanceSettingService
    {
        private readonly ILogger<MaintenanceSettingController> logger;
        private EquipmentCSVLinkRepository equipmentCSVLinkRepository;

        string connectionString = Environment.GetEnvironmentVariable("IOTRMS_BACKUP_BLOB_ACCOUNT_KEY");
        string containerName = Environment.GetEnvironmentVariable("IOTRMS_BACKUP_BLOB_ACCOUNT_CONTAINER_NAME");

        /// <summary>
        /// コンストラクター
        /// </summary>
        /// <param name="logger">ロガー</param>
        public MaintenanceSettingService(ILogger<MaintenanceSettingController> logger)
        {
            this.logger = logger;
            equipmentCSVLinkRepository = new EquipmentCSVLinkRepository(logger);
        }

        /// <summary>
        ///  その他タブ画面の装置ZIPファイル一覧を取得する
        ///    装置ZIPファイル一覧のプルダウン
        /// </summary>
        /// <param name="equipmentID">装置ID</param>
        /// <returns>装置ZIPファイル一覧のプルダウンデータ</returns>
        public IEnumerable<EquipmentCSVLinkEntity> GetCSVLinkEntity(int equipmentID)
        {
            return equipmentCSVLinkRepository.GetCSVLinkEntity(equipmentID);
        }

        /// <summary>
        /// Azure BLOB からメモリストリームにファイルを解凍してバイト形式で返す
        /// </summary>
        /// <param name="fileId">対象ZIPファイルId</param>
        /// <param name="path">Blob対象フォルダー</param>
        /// <returns>バイト形式ファイル</returns>
        public async Task<byte[]> GetZipFile(string fileId, string path)
        {
            BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);
            BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);

            MemoryStream ms = new MemoryStream();
            // ms記録内容を作成する
            using (ZipArchive archive = new ZipArchive(ms, ZipArchiveMode.Create))
            {
                // Blob からターゲット Path ファイルをフェッチする
                await foreach (BlobItem blob in containerClient.GetBlobsAsync(BlobTraits.None, BlobStates.None, path))
                {
                    // コンマ文字列を文字列配列に変換する
                    string[] csvId = fileId.Split(',').ToArray();
                    IEnumerable<EquipmentCSVLinkEntity> csvEntity = null;
                    // 選択したファイルをループする
                    foreach (string id in csvId)
                    {
                        // 対象csvPathを取得する
                        csvEntity = equipmentCSVLinkRepository.GetCSVpath(int.Parse(id));
                        foreach (var csv in csvEntity)
                        {
                            if (csv.CsvPath == blob.Name)
                            {
                                // blob記録作成
                                // blobファイル保存用メモリストリーム作成してファイルをストリームにダウンロードする
                                ZipArchive archive_blobFile = BlobFileToMemoryStream(containerClient, blob.Name);

                                // 各ストリームのBlobファイルを解凍する
                                foreach (ZipArchiveEntry entry in archive_blobFile.Entries)
                                {
                                    if (entry.FullName.EndsWith(".csv", StringComparison.OrdinalIgnoreCase))
                                    {
                                        // 解凍されたBlobファイルストリームをメモリストリームに保存する
                                        MemoryStream ms_unzippedEntryStream = new MemoryStream();
                                        // 解凍されたBlobファイルをストリームに仮保存
                                        Stream unzippedEntryStream = entry.Open();
                                        unzippedEntryStream.CopyTo(ms_unzippedEntryStream);

                                        // メモリストリームに保存された解凍ファイルをバイト形式ファイルに作成する
                                        ZipArchiveEntry ms_Entry = archive.CreateEntry(entry.Name); // Byteファイル名を設定する
                                        // BlobファイルコンテンツをByteファイルに追加する
                                        using (BinaryWriter writer = new BinaryWriter(ms_Entry.Open()))
                                        {
                                            // write the binary data
                                            writer.Write(ms_unzippedEntryStream.ToArray(), 0, ms_unzippedEntryStream.ToArray().Length);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return ms.ToArray();
        }

        /// <summary>
        /// Blobファイルをストリームに展開
        /// </summary>
        /// <param name="containerClient">コンテナ</param>
        /// <param name="blobName">対象BlobファイルPath</param>
        /// <returns>zip アーカイブ形式Blobファイル</returns>
        private ZipArchive BlobFileToMemoryStream(BlobContainerClient containerClient, string blobName)
        {
            MemoryStream ms_blobFile = new MemoryStream();
            BlobClient blobClient = containerClient.GetBlobClient(blobName);
            blobClient.DownloadTo(ms_blobFile);
            return new ZipArchive(ms_blobFile);
        }
    }
}

Lean Version

home

  1. Download Files from Azure Blob and Unzip them
namespace IotRmsWeb.Services.Equipment.Impl
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.IO.Compression;
    using System.Threading.Tasks;
    using Azure.Storage.Blobs;
    using IotRmsWeb.Commons;
    using IotRmsWeb.Entities;
    using IotRmsWeb.Repositories.Main;
    using IotRmsWeb.Services.Equipment;
    using Microsoft.Extensions.Logging;

    /// <summary>
    /// 装置情報過去データCSV出力用サービス
    /// </summary>
    public class DownloadZipFileService : IDownloadZipFileService
    {
        private readonly ILogger<DownloadZipFileService> logger;
        private EquipmentCSVLinkRepository equipmentCSVLinkRepository;

        /// <summary>
        /// コンストラクター
        /// </summary>
        /// <param name="logger">ログエントリロガー</param>
        public DownloadZipFileService(ILogger<DownloadZipFileService> logger)
        {
            this.logger = logger;
            this.equipmentCSVLinkRepository = new EquipmentCSVLinkRepository(this.logger);
        }

        /// <summary>
        ///  ハッシュ表ファイルを取得する
        /// </summary>
        /// <param name="equipmentID">装置ID</param>
        /// <returns>ハッシュ表ファイル</returns>
        public Dictionary<string, List<EquipmentCSVLinkEntity>> GetCSVLinkList(int equipmentID)
        {
            IEnumerable<EquipmentCSVLinkEntity> list = this.equipmentCSVLinkRepository.GetCSVLinkEntity(equipmentID);

            // Zipファイル一覧をハッシュ表に展開する
            Dictionary<string, List<EquipmentCSVLinkEntity>> settingItemList = new Dictionary<string, List<EquipmentCSVLinkEntity>>();

            foreach (var item in list)
            {
                if (item.DocTypeId == item.TelegramKind.ToString())
                {
                    item.CsvPathName = item.EquipmentDataOccurrenceDate + '_' + item.EquipmentName + '_' + item.DocTypeName + ".zip";

                    if (settingItemList.ContainsKey(item.DocTypeName))
                    {
                        settingItemList[item.DocTypeName].Add(item);
                    }
                    else
                    {
                        List<EquipmentCSVLinkEntity> settingItemData = new List<EquipmentCSVLinkEntity>();
                        settingItemData.Add(item);
                        settingItemList[item.DocTypeName] = settingItemData;
                    }
                }
                else
                {
                    // 空電文種類を作成する
                    if (!settingItemList.ContainsKey(item.DocTypeName))
                    {
                        settingItemList[item.DocTypeName] = new List<EquipmentCSVLinkEntity>();
                    }
                }
            }

            return settingItemList;
        }

        /// <summary>
        /// BLOBからダウンロードしたCsvファイルをバイト形式で取得する
        /// </summary>
        /// <param name="fileId">対象ファイルId</param>
        /// <param name="abnormalCheck">ダウンロードファイル異常確認</param>
        /// <returns>バイト形式ファイル</returns>
        public async Task<byte[]> GetCsvFile(string fileId, bool abnormalCheck)
        {
            // 対象ファイルデータを取得する
            IEnumerable<EquipmentCSVLinkEntity> csvEntity = this.equipmentCSVLinkRepository.GetZIPpath(fileId);

            var abnormalFile = false;
            var normalFile = 0;

            using MemoryStream ms = new MemoryStream();

            Dictionary<string, byte[]> unzipFile = new Dictionary<string, byte[]>();

            // ms記録オブジェクトを作成する
            using (ZipArchive archive = new ZipArchive(ms, ZipArchiveMode.Create))
            {
                foreach (EquipmentCSVLinkEntity csv in csvEntity)
                {
                    // BlobからダウンロードするZIPファイル一覧の取得
                    ZipArchive archiveBlob = await this.GetBlobFileAsync(csv.CsvPath);

                    if (archiveBlob == null)
                    {
                        // 無ファイル異常
                        abnormalFile = true;
                        continue;
                    }

                    // 取ったZIPファイルを解凍してms記録に保存する
                    unzipFile = this.UnZipBlob(archiveBlob);

                    if (unzipFile.Count == 0)
                    {
                        // 空ファイル異常
                        abnormalFile = true;
                        continue;
                    }

                    foreach (var item in unzipFile)
                    {
                        // Byteファイル名を設定する
                        ZipArchiveEntry ms_Entry = archive.CreateEntry(item.Key);

                        // BlobファイルコンテンツをByteファイルに追加する
                        using (BinaryWriter writer = new BinaryWriter(ms_Entry.Open()))
                        {
                            writer.Write(item.Value, 0, item.Value.Length);
                        }
                    }

                    normalFile++;
                }
            }

            // 正常のファイルが無かった時(空ファイル又は無Blobファイル)0バイトを却する
            if (normalFile == 0)
            {
                return new byte[0];
            }

            // 一部Blobファイルが異常時(空ファイル又は無Blobファイル)1バイトを却する
            if (abnormalFile == true && abnormalCheck == true)
            {
                return new byte[1];
            }

            return ms.ToArray();
        }

        /// <summary>
        /// BlobからダウンロードするZIPファイル一覧の取得
        /// </summary>
        /// <param name="fileName">Blob対象ファイル名称</param>
        /// <returns>メモリストリーム記録</returns>
        private async Task<ZipArchive> GetBlobFileAsync(string fileName)
        {
            string connectionString = Environment.GetEnvironmentVariable("IOTRMS_BACKUP_BLOB_CONNECTION_STRING");
            string containerName = Environment.GetEnvironmentVariable("IOTRMS_BACKUP_BLOB_ACCOUNT_CONTAINER_NAME");

            BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);
            BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);

            BlobClient blobClient = containerClient.GetBlobClient(fileName);

            if (blobClient.Exists())
            {
                MemoryStream ms_blobFile = new MemoryStream();
                await blobClient.DownloadToAsync(ms_blobFile);
                return new ZipArchive(ms_blobFile);
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// blobで取得したファイル一覧の解凍してバイト形式ファイル作成する
        /// </summary>
        /// <param name="archiveBlob">Blobファイル</param>
        /// <returns>バイト形式ファイル</returns>
        private Dictionary<string, byte[]> UnZipBlob(ZipArchive archiveBlob)
        {
            Dictionary<string, byte[]> unZippedBlob = new Dictionary<string, byte[]>();
            if (archiveBlob == null)
            {
                return unZippedBlob;
            }

            // 解凍されたBlobファイル保存用メモリストリームを作成する
            using (MemoryStream ms_unzippedEntryStream = new MemoryStream())
            {
                // 各ストリームのBlobファイルを解凍する
                foreach (ZipArchiveEntry entry in archiveBlob.Entries)
                {
                    // csv拡張子ファイル確認・空ファイル確認
                    if (entry.Length > 0 && entry.FullName.EndsWith(Const.CSV_FILE_NAME_SUFFIX, StringComparison.OrdinalIgnoreCase))
                    {
                        // 解凍されたBlobファイルをストリームに仮保存
                        Stream unzippedEntryStream = entry.Open();
                        unzippedEntryStream.CopyTo(ms_unzippedEntryStream);
                        unZippedBlob[entry.Name] = ms_unzippedEntryStream.ToArray();
                    }
                }
            }

            return unZippedBlob;
        }
    }
}
  1. Download Files from Azure Blob without unzip them
namespace IotRmsWeb.Services.Equipment.Impl
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Threading.Tasks;
    using ICSharpCode.SharpZipLib.Zip;
    using IotRmsWeb.Entities;
    using IotRmsWeb.Repositories.Main;
    using IotRmsWeb.Services.Equipment;
    using Microsoft.Azure.Storage;
    using Microsoft.Azure.Storage.Blob;
    using Microsoft.Extensions.Logging;

    /// <summary>
    /// 装置情報過去データCSV出力用サービス
    /// </summary>
    public class DownloadZipFileService : IDownloadZipFileService
    {
        private readonly ILogger<DownloadZipFileService> logger;
        private EquipmentCSVLinkRepository equipmentCSVLinkRepository;

        /// <summary>
        /// コンストラクター
        /// </summary>
        /// <param name="logger">ログエントリロガー</param>
        public DownloadZipFileService(ILogger<DownloadZipFileService> logger)
        {
            this.logger = logger;
            this.equipmentCSVLinkRepository = new EquipmentCSVLinkRepository(this.logger);
        }

        /// <summary>
        ///  ハッシュ表ファイルを取得する
        /// </summary>
        /// <param name="equipmentID">装置ID</param>
        /// <returns>ハッシュ表ファイル</returns>
        public Dictionary<string, List<EquipmentCSVLinkEntity>> GetCSVLinkList(int equipmentID)
        {
            IEnumerable<EquipmentCSVLinkEntity> list = this.equipmentCSVLinkRepository.GetCSVLinkEntity(equipmentID);

            // Zipファイル一覧をハッシュ表に展開する
            Dictionary<string, List<EquipmentCSVLinkEntity>> settingItemList = new Dictionary<string, List<EquipmentCSVLinkEntity>>();

            foreach (var item in list)
            {
                if (item.DocTypeId == item.TelegramKind.ToString())
                {
                    item.CsvPathName = item.EquipmentDataOccurrenceDate + '_' + item.EquipmentName + '_' + item.DocTypeName + ".zip";

                    if (settingItemList.ContainsKey(item.DocTypeName))
                    {
                        settingItemList[item.DocTypeName].Add(item);
                    }
                    else
                    {
                        List<EquipmentCSVLinkEntity> settingItemData = new List<EquipmentCSVLinkEntity>();
                        settingItemData.Add(item);
                        settingItemList[item.DocTypeName] = settingItemData;
                    }
                }
                else
                {
                    // 空電文種類を作成する
                    if (!settingItemList.ContainsKey(item.DocTypeName))
                    {
                        settingItemList[item.DocTypeName] = new List<EquipmentCSVLinkEntity>();
                    }
                }
            }

            return settingItemList;
        }

        /// <summary>
        /// BLOBからダウンロードしたCsvファイルをバイト形式で取得する
        /// </summary>
        /// <param name="fileId">対象ファイルId</param>
        /// <param name="abnormalCheck">ダウンロードファイル異常確認</param>
        /// <returns>バイト形式ファイル</returns>
        public async Task<byte[]> GetCsvFile(string fileId, bool abnormalCheck)
        {
            // 対象ファイルデータを取得する
            IEnumerable<EquipmentCSVLinkEntity> csvEntity = this.equipmentCSVLinkRepository.GetZIPpath(fileId);

            var blobFile = 0;
            var noBlobFile = false;

            using (MemoryStream ms = new MemoryStream())
            {
                var zipOutputStream = new ZipOutputStream(ms);
                foreach (EquipmentCSVLinkEntity csv in csvEntity)
                {
                    string[] strlist = csv.CsvPath.Split('/', ' ', StringSplitOptions.RemoveEmptyEntries);
                    var entry = new ZipEntry(strlist[2]);
                    

                    // Blobファイルを取得する
                    var blob = GetBlobFileAsync(csv.CsvPath);

                    if (blob == null)
                    {
                        //無ファイル異常
                        noBlobFile = true;
                        continue;
                    }

                    // ファイル名をメモリストリームに書き込む
                    zipOutputStream.PutNextEntry(entry);

                    // Blobファイルをメモリストリームにダウンロードする
                    await blob.DownloadToStreamAsync(zipOutputStream);

                    blobFile++;
                }

                // Reset memory stream
                zipOutputStream.Finish();
                zipOutputStream.IsStreamOwner = false;
                ms.Position = 0; 


                // 無Blobファイル時0バイトを却する
                if (blobFile == 0)
                {
                    return new byte[0];
                }

                // 一部Blobファイルが無し時1バイトを却する
                if (noBlobFile == true && abnormalCheck == true)
                {
                    return new byte[1];
                }

                return ms.ToArray();
            }
        }

        /// <summary>
        /// Blobからファイル一覧の取得
        /// </summary>
        /// <param name="fileName">Blob対象ファイル名称</param>
        /// <returns>取得したBlobファイル</returns>
        private CloudBlockBlob GetBlobFileAsync(string fileName)
        {
            string connectionString = Environment.GetEnvironmentVariable("IOTRMS_BACKUP_BLOB_CONNECTION_STRING");
            string containerName = Environment.GetEnvironmentVariable("IOTRMS_BACKUP_BLOB_ACCOUNT_CONTAINER_NAME");

            CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(connectionString);
            CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
            CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference(containerName);

            var getBlobFile = cloudBlobContainer.GetBlockBlobReference(fileName);

            if (getBlobFile.Exists() == false)
            {
                return null;
            }

            return getBlobFile;
        }
    }
}
Clone this wiki locally