将文件转换成Base64编码和file对象上传文件
下文中,将文件转换成Base64编码上传文件,简称为:Base64。file对象上传文件,简称为:file。
本文主要以上传图片为例,如果上传其他类型的文件,可能会有一些差异。
HTML
<div class="layui-fluid">
<div class="layui-col-lg6 col_left">
<div class="col_title">Base64上传文件</div>
<div class="btn_file">
<button type="button" class="layui-btn" id="btn_base64" onclick="f_base64.click();"><i class="layui-icon"></i>上传图片<sapn class="time_base64"></sapn></button>
<input type="file" id="f_base64" multiple="multiple" accept="image/jpg,image/jpeg,image/png" style="display:none;" onchange="UpfileCheck(this,'base64')" />
</div>
<div class="preview_img_base64">
<div class="col_title">Img</div>
</div>
<div class="preview_bimg_base64">
<div class="col_title">Background-image</div>
</div>
</div>
<div class="layui-col-lg6 col_right">
<div class="col_title">file对象上传文件</div>
<div class="btn_file">
<button type="button" class="layui-btn" id="btn_file" onclick="f_flie.click();"><i class="layui-icon"></i>上传图片<sapn class="time_files"></sapn></button>
<input type="file" id="f_flie" multiple="multiple" accept="image/jpg,image/jpeg,image/png" style="display:none;" onchange="UpfileCheck(this,'files')" />
</div>
<div class="preview_img_files">
<div class="col_title">Img</div>
</div>
<div class="preview_bimg_files">
<div class="col_title">Background-image</div>
</div>
</div>
</div>
CSS
<link rel="stylesheet" href="/css/style.css" />
<link rel="stylesheet" href="/js/layui/css/layui.css">
<style type="text/css">
.layui-fluid {
padding: 10px;
}
.col_left {
border-right: 1px solid rgb(203, 200, 200);
}
.col_right {
padding-left: 10px;
}
.col_title {
font-size: 16px;
font-weight: bold;
text-align: center;
}
.preview_img_base64, .preview_bimg_base64 {
margin-top: 10px;
}
.preview_img_base64 img {
width: 150px;
height: 150px;
object-fit: cover;
box-shadow: 0 1px 5px rgba(0,0,0,.2);
}
.preview_bimg_photo {
height: 150px;
width: 150px;
background: no-repeat 50%;
background-size: cover;
box-shadow: 0 1px 5px rgba(0,0,0,.2);
float: left;
}
.preview_img_files, .preview_bimg_files {
margin-top: 10px;
}
.preview_img_files img {
width: 150px;
height: 150px;
object-fit: cover;
box-shadow: 0 1px 5px rgba(0,0,0,.2);
}
</style>
JS
<script src="/js/layui/layui.js"></script>
<script src="/js/jquery/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
var fl = 0;//文件数量
var upload_num = 0;//文件上传索引
var file_array = [];//文件数组
var upload_mask;//文件上传遮罩
var st_base64;//base64上传文件开始时间
var st_files;//file对象上传文件开始
var et_base64;//base64上传文件结束时间
var et_files;//file对象上传文件结束时间
//文件上传初始化
function UpfileCheck(t, upload_flag) {
fl = t.files.length;//获取文件数量
upload_num = 0;//初始化文件上传索引
file_array = [];//文件数组
//需要判断是否选择图片,否则第一次选择图片后,第二次选择图片取消也会触发上传
if (fl > 0) {
upload_mask = layer.load(1, {
content: '上传中...',
shade: [0.4, '#393D49'],
success: function (layero) {
layero.find('.layui-layer-content').css({
'padding-top': '39px',
'width': '200px',
'color': '#fff',
'text-align': 'left'
});
}
});
if (upload_flag == 'base64') {
st_base64 = new Date();
console.log(st_base64);
setTimeout(function () { UpfileBase64(t, upload_num); }, 500);
}
else {
st_files = new Date();
console.log(st_files);
setTimeout(function () { UpfileFiles(t, upload_num);}, 500);
}
}
else {
layer.msg('请选择需要上传的文件!');
}
}
//将文件转换为base64编码
function UpfileBase64(t, f_num) {
var filename = t.files[f_num].name;//文件名
var houzui = filename.lastIndexOf('.'); //获取 . 出现的位置
var ext = filename.substring(houzui, filename.length).toUpperCase(); //切割 . 获取文件后缀
var reader = new FileReader();
reader.readAsDataURL(t.files[f_num]); //将读取到的文件编码成Data URL
reader.onload = function () { //读取完成时
var replaceSrc = reader.result; //文件输出的内容
//将文件放入文件数组中
file_array.push({ base64_code: replaceSrc, filename: filename, ext: ext, src: '/upload/img/' });
upload_num++;
if (upload_num >= fl) {
AjaxUploadBase64(); //ajax上传base64编码的文件
$("#f_base64").val("");//清空文件控件
}
else {
UpfileBase64(t, upload_num);//继续读取文件
}
}
}
//ajax上传base64编码的文件
function AjaxUploadBase64() {
//判断文件数组中是否存在文件
if (file_array.length > 0) {
//遍历数组中的文件上传到应用服务器
for (var i = 0; i < file_array.length; i++) {
$.ajax({
type: "post",
url: "/UploadFile/ashx/UploadImg.ashx",
data: { fun: "UploadImgBase64", strbase64: file_array[i]["base64_code"], src: file_array[i]["src"], filename: file_array[i]["filename"] },
dataType: "json",
async: false,
success: function (data) {
if (data.ajaxDataFlag) {
PreviewBImg(data.ajaxresult, 'Base64');//预览图片
}
else {
layer.msg("上传失败:" + data.ajaxresult);
}
},
error: function (event, XMLHttpRequest, ajaxOptions, thrownError) {
// thrownError 只有当异常发生时才会被传递 this;
var resStr = event.statusText
layer.msg("上传失败:" + resStr);
}
});
}
}
layer.close(upload_mask);
et_base64 = new Date();
console.log(et_base64);
}
//使用file对象上传文件
function UpfileFiles(t, f_num) {
var imgData = new FormData();
imgData.append('fun', 'UploadImgFiles');//文件上传方法名
imgData.append('file', t.files[f_num]);//file对象
imgData.append('src', "/upload/img/");//上传文件存放地址
$.ajax({
type: "POST",
url: "/UploadFile/ashx/UploadImg.ashx",
data: imgData,
processData: false,//防止将发送的数据序列
contentType: false,//默认值: true。默认情况下,通过data选项传递进来的数据,如果是一个对象(技术上讲只要不是字符串),都会处理转化成一个查询字符串,以配合默认内容类型 “application/x-www-form-urlencoded”。如果要发送 DOM 树信息或其它不希望转换的信息,请设置为 false。
dataType: "json",
async: false,
success: function (data) {
PreviewBImg(data.ajaxresult, 'Files');//预览图片
upload_num++;//更新文件索引
//文件未上传完成继续上传
if (upload_num < fl) {
UpfileFiles(t, upload_num);//继续上传
}
else {
et_files = new Date();
console.log(et_files);
layer.close(upload_mask);
}
},
error: function (event, XMLHttpRequest, ajaxOptions, thrownError) {
// thrownError 只有当异常发生时才会被传递 this;
var resStr = event.statusText
layer.msg("上传失败:" + resStr);
}
})
}
//预览图片
function PreviewBImg(src, up_flag) {
var htmlimg = "<img src='" + src + "' />";
var htmlbimg = "<div style='background-image:url(" + src + ")' class='preview_bimg_photo'> </div>";
if (up_flag == 'Base64') {
$(".preview_img_base64").append(htmlimg);
$(".preview_bimg_base64").append(htmlbimg);
}
else if (up_flag == 'Files') {
$(".preview_img_files").append(htmlimg);
$(".preview_bimg_files").append(htmlbimg);
}
}
</script>
一般处理程序
#region ajax上传base64编码的文件
public string UploadImgBase64(HttpContext context)
{
string strbase64 = context.Request.QueryString["strbase64"] ?? context.Request.Form["strbase64"];
string src = context.Request.QueryString["src"] ?? context.Request.Form["src"];
string filename = context.Request.QueryString["filename"] ?? context.Request.Form["filename"];
try
{
//获取base64编码
string dummyData = strbase64.Replace("data:audio/mp3;base64,", "").Replace("data:application/pdf;base64,", "").Replace("data:image/gif;base64,", "").Replace("data:image/jpeg;base64,", "").Replace("data:image/png;base64,", "").Replace("%", "").Replace(",", "").Replace(" ", "+");
if (dummyData.Length % 4 > 0)
{
dummyData = dummyData.PadRight(dummyData.Length + 4 - dummyData.Length % 4, '=');
}
//文件上传路径+年月日
src = src + DateTime.Now.ToString("yyMMdd") + "/";
string uploadPath = context.Request.PhysicalApplicationPath + src;//获取文件在应用服务器存放的绝对路径
//判断文件上传路径文件夹是否存在
if (!Directory.Exists(uploadPath))
{
Directory.CreateDirectory(uploadPath);//创建文件夹
}
//上传文件
FileStream fs = null;
Random rd = new Random();
fs = File.Create(uploadPath + filename);
byte[] bytes = Convert.FromBase64String(dummyData);
fs.Write(bytes, 0, bytes.Length);
fs.Close();//释放资源,否则图片一直被占用
//文件HTTP路径,域名+端口+文件上传路径+文件名
string httpPath = "http://" + context.Request.Url.Host + ":" + context.Request.Url.Port + src + filename;
at.ajaxDataFlag = true;
at.ajaxresult = httpPath;
}
catch (Exception ex)
{
at.ajaxDataFlag = false;
at.ajaxresult = "服务器内部错误,请联系开发人员!";
ALogOut.debug(ex.ToString());//记录错误日志
}
return JsonConvert.SerializeObject(at);//返回结果
}
#endregion
#region 使用file对象上传文件
public string UploadImgFiles(HttpContext context)
{
HttpPostedFile files = context.Request.Files["file"];
string src = context.Request.QueryString["src"] ?? context.Request.Form["src"];
try
{
//文件上传路径+年月日
src = src + DateTime.Now.ToString("yyMMdd") + "/";
string uploadPath = context.Request.PhysicalApplicationPath + src;//获取文件在应用服务器存放的绝对路径
//判断文件上传路径文件夹是否存在
if (!Directory.Exists(uploadPath))
{
Directory.CreateDirectory(uploadPath);//创建文件夹
}
//上传文件至应用服务器
files.SaveAs(uploadPath + files.FileName);
Image pic = Image.FromFile(uploadPath + files.FileName);//图片的绝对路径
int intWidth = pic.Width;//长度像素值
int intHeight = pic.Height;//高度像素值
pic.Dispose();//释放资源
//文件HTTP路径,域名+端口+文件上传路径+文件名
string httpPath = "http://" + context.Request.Url.Host + ":" + context.Request.Url.Port + src + files.FileName;
at.ajaxDataFlag = true;
at.ajaxresult = httpPath;
at.ajaxString = uploadPath + files.FileName;//文件在应用服务器的绝对路径
}
catch (Exception ex)
{
at.ajaxDataFlag = false;
at.ajaxresult = "服务器内部错误,请联系开发人员!";
ALogOut.debug(ex.ToString());
}
return JsonConvert.SerializeObject(at);
}
#endregion
页面效果
页面分为了“Base64上传文件”和“file对象上传文件”左右两部分,用于对两种上传方式进行测试,同时针对图片展示分为了“img”和“Background-image”两种方式呈现。
测试结果:
1.在不设置上传文件上传大小的情况下,Base64上传的图片大小为2~3M,file上传的文件大小不能大于等于4M。
2.设置文件上传大小为500M后,Base64无法上传超过20M的图片,file可以上传20M以上的图片(上限未测试)。(web.config配置)
3.file上传文件比Base64更快。
4.img和Background-image图片显示速度相同。
5.Background-image无法显示文件名带有特殊字符的图片,如:空格、()等。(解决方案:一是上传时不允许上传文件名带有特殊字符或者重命名取消特殊字符。二是将文件名中的特殊字符进行转义。)
6.file上传图片时,可以在一般处理程序中获取图片的尺寸,详情见代码。