最近、バッチアルバム管理機能の実装においてiViewのアルバムコンポーネントを利用しました。このコンポーネントのドキュメントはこちらから参照できます:https://www.iviewui.com/components/upload
まずは完成したイメージをご紹介します。
実装の主な难点は、ドキュメントに記載されているパラメータの具体的な記述方法が不明な点でしたが、コミュニティの助けを得て解決することができました。具体的な実装は以下の通りです。デフォルトではアップロード時に直接データベースに記録し、ログには更新された画像のログIDを追加します。削除処理は保存ボタンクリック後に実行され、削除対象のIDをバックエンドで処理し、画像ファイルとデータベースの両方から削除します。アップロード時にはページの検証用隠しフィールドパラメータを付与します。以下に実装コードを記載します。
<div id="app">
<div class="demo-upload-list" v-for="item in fileList">
<template v-if="item.status === 'finished'">
<img :src="item.url">
<div class="demo-upload-list-cover">
<icon type="ios-eye-outline" @@click.native="previewImage(item.url)"></icon>
<icon type="ios-trash-outline" @@click.native="removeFile(item)"></icon>
</div>
</template>
<template v-else>
<i-progress v-if="item.showProgress" :percent="item.percentage" hide-info></i-progress>
</template>
</div>
<upload ref="uploader"
:show-upload-list="false"
:default-file-list="initialFiles"
:on-success="uploadCompleted"
:format="['jpg','jpeg','png']"
:max-size="2048"
:on-format-error="formatError"
:on-exceeded-size="sizeExceeded"
:before-upload="beforeUpload"
:data="{'ProjectID':projectId, 'LogID':logId, 'VerificationToken':csrfToken}"
multiple
type="drag"
name="uploadedFile"
action="/ProjectBudget/ProjectLog/ProcessImage"
style="display: inline-block;width:58px;">
<div style="width: 58px;height:58px;line-height: 58px;">
<icon type="camera" size="20"></icon>
</div>
</upload>
<modal title="画像プレビュー" v-model="previewVisible">
<a :href="previewUrl" target="_blank"><img :src="previewUrl" v-if="previewVisible" style="width: 100%"></a>
</modal>
</div>
var csrfToken = $("input[name='__RequestVerificationToken']").val();
//Vueアルバムの初期化
var App = {
data() {
return {
initialFiles: initialImageData,
projectId: ProjectID,
logId: keyValue,
csrfToken: csrfToken,
previewUrl: '',
previewVisible: false,
fileList: []
}
},
methods: {
previewImage(url) {
this.previewUrl = url;
this.previewVisible = true;
},
removeFile(file) {
deletedFileIDs += file.name + ',';
const currentFiles = this.$refs.uploader.fileList;
this.$refs.uploader.fileList.splice(currentFiles.indexOf(file), 1);
},
uploadCompleted(response, file) {
file.url = response.message.split('|')[0];
file.name = response.message.split('|')[1];
},
formatError(file) {
this.$Notice.warning({
title: '画像フォーマットが不正です',
desc: 'フォーマットが許可されていないファイル:' + file.name + '。jpgまたはpng形式の画像をアップロードしてください。'
});
},
sizeExceeded(file) {
this.$Notice.warning({
title: 'ファイルサイズが上限を超えています',
desc: 'ファイル ' + file.name + ' は2MBのサイズ制限を超えています。'
});
},
beforeUpload() {
const isValid = this.fileList.length < 10;
if (!isValid) {
this.$Notice.warning({
title: '最大10枚までアップロード可能です。'
});
}
return isValid;
}
},
mounted() {
this.fileList = this.$refs.uploader.fileList;
}
}
var Application = Vue.extend(App)
new Application().$mount('#app')
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ProcessImage(HttpPostedFileBase uploadedFile, HttpPostedFileBase afterFile, string ProjectID, string LogID)
{
if (uploadedFile != null)
{
if (!string.IsNullOrEmpty(uploadedFile.FileName))
{
var uniqueFileName = string.Format("{0:yyyyMMddHHmmss}", DateTime.Now) + ".jpg";
ProcessImageUpload(uploadedFile, uniqueFileName);
//情報を保存
var imageEntity = new ProjectImageEntity();
imageEntity.ImagePath = "/Resource/ProjectLog/" + uniqueFileName;
imageEntity.ImageType = (int)ImageProgressType.BeforeWork;
imageEntity.LogID = LogID;
imageEntity.ProjectID = ProjectID;
string newId = "";
if (imageApp.AddForm(imageEntity, out newId) == true)
{
return Success("/Resource/ProjectLog/" + uniqueFileName + "|" + newId);
}
else
{
return Error("アップロードに失敗しました");
}
}
}
if (afterFile != null)
{
if (!string.IsNullOrEmpty(afterFile.FileName))
{
var uniqueFileName = string.Format("{0:yyyyMMddHHmmss}", DateTime.Now) + ".jpg";
ProcessImageUpload(afterFile, uniqueFileName);
//情報を保存
var imageEntity = new ProjectImageEntity();
imageEntity.ImagePath = "/Resource/ProjectLog/" + uniqueFileName;
imageEntity.ImageType = (int)ImageProgressType.AfterWork;
imageEntity.LogID = LogID;
imageEntity.ProjectID = ProjectID;
string newId = "";
if (imageApp.AddForm(imageEntity, out newId) == true)
{
return Success("/Resource/ProjectLog/" + uniqueFileName + "|" + newId);
}
else
{
return Error("アップロードに失敗しました");
}
}
}
return Error("アップロードに失敗しました");
}
public bool ProcessImageUpload(HttpPostedFileBase file, string fileName)
{
if (file == null)
{
return false;
}
try
{
var destinationPath = Server.MapPath("~/Resource/ProjectLog/");
if (!Directory.Exists(destinationPath))
{
Directory.CreateDirectory(destinationPath);
}
string fullPath = Path.Combine(destinationPath, fileName);
file.SaveAs(fullPath);
//画像サイズのチェックとトリミング
Thumbnail.MakeThumbnailImage(fullPath, fullPath, 800, 800);
//タイムスタンプ付きテキストウォーターマークの追加
WaterMark.AddImageSignText(fullPath, fullPath, string.Format("{0:yyyy-MM-dd HH:mm:ss}", DateTime.Now), 9, 80, "Tahoma", 14);
}
catch (Exception ex)
{
Logger logger = LoggerFactory.GetLogger(this.GetType().ToString());
logger.Error(string.Format("{0:yyyy-MM-dd HH:mm:ss}", DateTime.Now) + " 画像アップロード中に例外が発生——" + ex.ToString() + "\r\n\r\n\r\n");
return false;
}
return true;
}