-
Notifications
You must be signed in to change notification settings - Fork 0
memory stream
KS LIM edited this page Nov 9, 2022
·
6 revisions
■ 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 |
- 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
})
- 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");
}
- 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();
}
}
- 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();
}
[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);
}
}
}
- 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;
}
}
}
- 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;
}
}
}