Vue实现图片上传、保存和读取
前段时间收到一个开发任务,在原有功能基础上增加一个上传图片的功能,对于一个入职半年没这方面经验的新人来说有一定难度。在实现过程中,很多细节问题都是通过百度解决的,下面分享我的解决方法(截取部分代码),写的不好或者不对的地方,欢迎各位朋友不吝赐教。
主体思路:
- 先把图片上传到一个临时文件夹中,上传成功后可以点击预览,保存时,以字节数组形式读取临时文件夹中的图片,读取完成立即清除临时文件夹中的图片,将包含图片信息的字节数组作为一个变量存入数据库中
- 读取图片同理,将从数据库中读取到的字节数组转为Base64字符串,传到JS中作为图片的src,即可显示图片。
1、前端使用的是vue-element,代码如下:
<el-form-item label="上传模板图片:" v-if="carryForm.childTemplateType!='网点直连'" prop="TemplateFileName">
<el-upload class="upload-demo" style="width:600px;"
multiple="false"
drag
ref="upload"
action="/UpLoadFile/TemplateBasicsUpLoadPic"
:before-upload="checkUploadPic"
:on-change="handleChangePic"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:on-success="HandleSuccess">
<i class="el-icon-upload"></i>
<div class="el-upload__text" v-html="mainInfo.PageTitle[0]"></div>
</el-upload>
<el-dialog :visible.sync="innerVisible" :width="width" append-to-body>
<el-form :model="templatePicForm">
<el-image style="width:auto; height: auto"
:src="dialogImageUrl">
</el-image>
</el-form>
</el-dialog>
<span id="TipHint" style="position:absolute;top:230px;left:2px;color:red;" hidden>点击可预览图片</span>
</el-form-item>
关于element的上传组件的使用,推荐一个网站,非常方便还有实例:Element-Upload,建议收藏!
Action方法TemplateBasicsUpLoadPic放在外部控制器里面,上传的图片保存到临时文件夹TemplFiles中,上传成功返回图片路径:
public string TemplateBasicsUpLoadPic()
{
try
{
var fs = HttpContext.Request.Files;
if (fs == null || fs.Count == 0) return "";
var file = fs[0];
var savePath = $"{AppDomain.CurrentDomain.BaseDirectory}TemplFiles\\{file.FileName}";
var dirName = Path.GetDirectoryName(savePath);
if (!Directory.Exists(dirName)) Directory.CreateDirectory(dirName);
file.SaveAs(savePath);
return savePath;
}
catch
{
return "";
}
}
2、JS代码,由于数据库中存储图片的字段设定的是blob类型,最大只能存储65KB的内容,但是我在自己调试的时候发现64到65KB大小的图片也是无法保存的,所以在上传时限制在64KB以内
- tinyblob:仅255个字符
- blob:最大限制到65K字节
- mediumblob:限制到16M字节
- longblob:可达4GB
data:{
......
dialogImageUrl: '',
width: '',
innerVisible: false,//图片预览Dialog初始不显示
templatePicForm: {
},
......
},
methods:{
......
checkUploadPic(file) {
let _this = this;
if (!(file.type === 'image/png' || file.type === 'image/gif' || file.type === 'image/jpg' || file.type === 'image/jpeg')) {
$.msg.warning("上传文件不是图片,请重新选择!");
return false;
}
let size = file.size / 1024;
if (size > 64) {
$.msg.warning("图片必须小于64KB!");
return false;
}
_this.carryForm.TemplateFileName = file.name;
},
handleChangePic(file, fileList) {
if (fileList.length > 1) {
$.msg.warning("仅限上传一张图片,请先清除,再上传!");
this.fileList = fileList.splice(-1);
}
},
//on-preview 点击文件列表中已上传的文件时的钩子(预览图片弹窗)
handlePictureCardPreview(file) {
let _this = this;
this.width = 0 + 'px';
var windowURL = window.URL || window.webkitURL;
var dataURL = windowURL.createObjectURL(file.raw);
this.dialogImageUrl = dataURL;
var img = new Image();
img.src = dataURL;
img.onload = function () {
if (img.width > window.innerWidth) _this.width = window.innerWidth - 40 + 'px';
else _this.width = img.width + 50 + 'px';
};
this.innerVisible = true;//显示图片预览Dialog
},
HandleSuccess(response, file, filelist) {
let _this = this;
if (response != "") {
_this.carryForm.ImagePath = response;
this.$message({ showClose: true, message: '上传成功!', type: 'success' });
this.$refs.carryFormRef.valid = true;
$("#TipHint").show();
setTimeout(function () {
$("#TipHint").hide();
}, 2000);
}
else
$.msg.error("上传失败,请检查!");
},
handleRemove(file) {//对上传成功的图片进行删除
let _this = this;
$.post('/Print/TemplatebasicsOperate/DeleteFile?Url=' + file.response).then(function () {
});
},
......
}
删除临时文件夹中上传成功的图片:
public void DeleteFile(String Url)
{
if (Url != "undefined")
{
try
{
File.ReadAllBytes(Url);
var dirName = Path.GetDirectoryName(Url);
if (Directory.Exists(dirName)) File.Delete(Url);
}
catch (Exception ex) { }
}
}
3、点击保存后,JS提交数据到Controller后,转逻辑层进行处理,读取临时文件夹中的图片,保存为字节数组,将该数组存入数据库:
......
try
{
byte[] byData = null;
byData = File.ReadAllBytes(model.ImagePath);//读取图片保存到字节数组
string extensionName = System.IO.Path.GetExtension(model.ImagePath);//获取文件后缀名
var dirName = Path.GetDirectoryName(model.ImagePath);
if (Directory.Exists(dirName))//读取完删除临时文件
{
DirectoryInfo dir = new DirectoryInfo(dirName);
FileSystemInfo[] fileinfo = dir.GetFileSystemInfos();
foreach (FileSystemInfo i in fileinfo)
{
File.Delete(i.FullName);
}
}
if (UpFileIsLegal(model.ImagePath))
{
model.TemplatePic = byData;//把字节数组赋给存储对象
}
}
catch (Exception ex)
{
Plugins.LogManager.Error(ex);
}
......
4、从数据库中读取图片:
/// <summary>
/// 图片预览
/// </summary>
/// <param name="TemplateNo"></param>
/// <returns>Base64字符流</returns>
public String TemplatePicview(int TemplateNo)
{
string sql = "SELECT TemplatePic FROM tt_print_templatebasics WHERE TemplateNo=@TemplateNo ";
using (var connection = DapperConnection.GetConnectionDatabase("ERP_Master"))
{
byte[] _byte = null;
_byte = connection.Query<byte[]>(sql, new { TemplateNo }).FirstOrDefault();//用byte数据接收二进制数据
if (_byte != null)
{
string srcBase64Str = "data:image/png;base64," + Convert.ToBase64String(_byte);
return srcBase64Str;//srcBase64Str返到JS后,可直接作为图片的src
}
return "false";
}
}
<!--图片弹窗-->
<el-dialog style="font-weight: bold;margin-top:-35px !important;" title="图片预览" :visible.sync="dialogPicFormVisible" v-if="dialogPicFormVisible" :close-on-click-modal="false" :width="width" @@close="dialogClose">
<el-form :model="templatePicForm">
<el-image style="width:auto; height: auto"
:src="templatePicFormsrc">
</el-image>
</el-form>
<div slot="footer" class="dialog-footer" style="text-align:center;">
<el-button v-on:click="dialogPicFormVisible = false">关闭</el-button>
</div>
</el-dialog>
data: {
......
dialogPicFormVisible: false,
width: '',
......
},
......
//预览
PreviewTemplateInfo: function (row) {
var templateID = "1" + row.TemplateNo;
let _this = this;
$.get('/print/TemplatebasicsInfo/TemplatePicview?TemplateNo=' + row.TemplateNo).then(function (result) {
if (result != "false") {
_this.templatePicFormsrc = result;
var img = new Image();
img.src = result;
img.onload = function () {//此方法作用是限制图片大小不会超出屏幕范围
if (img.width > window.innerWidth) _this.width = window.innerWidth - 40 + 'px';
else _this.width = img.width + 50 + 'px';
};
_this.dialogPicFormVisible = true;
}
else {
$.msg.warning("预览失败!未查询到图片");
}
});
},
......
5、效果图:
点击选择图片上传:
图片上传成功,点击×可以删除图片:
点击图片名预览: