您的位置:首页 > 编程语言 > C#

简单文件分块上传 c#后台

2018-08-10 11:42 52 查看

vue code

<style>
.upload_warp_img_div_del {
position: absolute;
top: 6px;
width: 16px;
right: 4px;
}

.upload_warp_img_div_top {
position: absolute;
top: 0;
width: 100%;
height: 30px;
background-color: rgba(0, 0, 0, 0.4);
line-height: 30px;
text-align: left;
color: #fff;
font-size: 12px;
text-indent: 4px;
}

.upload_warp_img_div_text {
white-space: nowrap;
width: 80%;
overflow: hidden;
text-overflow: ellipsis;
}

.upload_warp_img_div img {
max-width: 100%;
max-height: 100%;
vertical-align: middle;
}

.upload_warp_img_div {
position: relative;
/*height: 100px;
width: 120px;*/
border: 1px solid #ccc;
margin: 0px 30px 10px 0px;
float: left;
line-height: 100px;
display: table-cell;
text-align: center;
background-color: #eee;
cursor: pointer;
}

.upload_warp_img {
border-top: 1px solid #D2D2D2;
padding: 14px 0 0 14px;
overflow: hidden;
}

.upload_warp_text {
text-align: left;
margin-bottom: 10px;
padding-top: 10px;
text-indent: 14px;
border-top: 1px solid #ccc;
font-size: 14px;
}

.upload_warp_right {
float: left;
width: 57%;
margin-left: 2%;
height: 100%;
border: 1px dashed #999;
border-radius: 4px;
line-height: 130px;
color: #999;
}

.upload_warp_left img {
margin-top: 32px;
}

.upload_warp_left {
/*float: left;
width: 40%;*/
height: 100%;
border: 1px dashed #999;
border-radius: 4px;
cursor: pointer;
text-align:center;
}

.upload_warp {
margin: 14px;
height: 130px;
}

.upload {
border: 1px solid #ccc;
background-color: #fff;
/*width: 650px;*/
box-shadow: 0px 1px 0px #ccc;
border-radius: 4px;
}

.hello {
width: 400px;
/*margin-left: 34%;*/
}
</style>
<div class="page-container" id="RoundRobinOperate">

<div class="row cl">
<label class="form-label col-xs-4 col-sm-2">文件:</label>
<div class="formControls col-xs-8 col-sm-9">
<div class="hello">
<label class="" style="color:red;" v-show="error_tips['ImgFile']!=''"><sup>*</sup>{{error_tips['ImgFile']}}</label>
<div class="upload">
<div class="upload_warp">
<div class="upload_warp_left" @@click="fileClick('ImgFile')" @@drop="drop($event,'ImgFile')" @@dragenter="dragenter($event)" @@dragover="dragover($event)">
<img src="@Url.Content("~/Content/img/upload.png")"><br />點擊或將文件拖到此處
</div>
</div>
<div class="upload_warp_text">
共{{bytesToSize(temp_ImgFile['ImgFile'].size)}}
</div>
<input @@change="fileChange($event,'ImgFile')" type="file" id="ImgFile" accept="image/png, image/jpeg, image/gif, image/jpg" style="display: none" />
<div class="upload_warp_img" v-show="temp_ImgFile['ImgFile'].url!=''">
<div class="upload_warp_img_div">
<div class="upload_warp_img_div_top">
<div class="upload_warp_img_div_text">
{{temp_ImgFile['ImgFile'].progress}}&nbsp;{{temp_ImgFile['ImgFile'].name}}
</div>
<img src="@Url.Content("~/Content/img/del.png")" class="upload_warp_img_div_del" @@click="fileDel('ImgFile')">
</div>
<img :src="temp_ImgFile['ImgFile'].url">
</div>
</div>
</div>
<button @@Click="readFile('ImgFile')" class="btn btn-primary radius" type="button"><i class="Hui-iconfont">&#xe632;</i> 上傳</button>
</div>
</div>
</div>

</div>

<script type="text/javascript">
var _uploadFileUrl = "@Url.Content("~/RoundRobin/uploadFile")";
var _root_path = "@Url.Content("~/")";
$(function () {
_vue_RoundRobinOperate = new Vue({
el: "#RoundRobinOperate",
name: "RoundRobinOperate",
data: function () {
return {
root_path: _root_path
, temp_ImgFile: { ImgFile: { url: "", size: 0, progress: "", name: "" }, ImgFileTra: { url: "", size: 0, progress: "", name: "" }, ImgFileSimp: { url: "", size: 0, progress: "", name: "" } }
, error_tips: { ImgFile: "", ImgFileTra: "", ImgFileSimp :"",submit:""}

, imgList: {}
, transmission_dataS:{}
};
},
created: function () {

},
methods: {
fileClick(lang) {
document.getElementById(lang).click();
},
fileChange(el, lang) {
if (!el.target.files[0].size) return;
this.fileAdd(el.target.files[0], lang);
el.target.value = ''
},
fileAdd(file, lang) {
//判断是否为图片文件 不属于图片文件的话,给一个默认图片作为预览图
if (file.type.indexOf('image') == -1) {
let _this = this;
_this.temp_ImgFile[lang] = { url:"@Url.Content("~/Content/img/wenjian.png")", size: file.size, progress: "未上傳", name: file.name };
_this.imgList[lang] = file;
} else {
let reader = new FileReader();
let _this = this;
reader.readAsDataURL(file);
reader.onload = function () {
_this.temp_ImgFile[lang] = { url: this.result, size: file.size, progress: "未上傳", name: file.name };
_this.imgList[lang] = file;
}
}
},
fileDel(lang) {
this.temp_ImgFile[lang] = { url: "", size: 0, progress: "", name: "" };
delete this.imgList[lang];
},
bytesToSize(bytes) {
if (bytes === 0) return '0 B';
let k = 1000, // or 1024
sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
i = Math.floor(Math.log(bytes) / Math.log(k));
return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i];
},
dragenter(el) {
el.stopPropagation();
el.preventDefault();
},
dragover(el) {
el.stopPropagation();
el.preventDefault();
},
drop(el, lang) {
el.stopPropagation();
el.preventDefault();
this.fileAdd(el.dataTransfer.files[0], lang);
},

uploadFile: function (pack, lang) {
axios.post(_uploadFileUrl, { "data": pack }).then(function (response) {
var obj = response.data;
if (obj.type == 0 || obj.type == 1) {
var pct = ((parseFloat(_vue_RoundRobinOperate.transmission_dataS[obj.packId].packIndex + 1) / parseFloat(_vue_RoundRobinOperate.transmission_dataS[obj.packId].packCount)) * 100).toFixed(2);
_vue_RoundRobinOperate.temp_ImgFile[lang].progress = "上傳中 " + pct + "%";
//console.log(pct + "%");
}
if (obj.type == 0) {
var transmission_data = _vue_RoundRobinOperate.transmission_dataS[obj.packId];
transmission_data.packIndex = obj.packIndex;
if (transmission_data.packIndex < transmission_data.packCount - 1) {
_vue_RoundRobinOperate.sendPack(1, transmission_data, lang);
} else {
_vue_RoundRobinOperate.sendPack(2, transmission_data, lang);
}
} else if (obj.type == 1) {
_vue_RoundRobinOperate.temp_ImgFile[lang].progress = "上傳成功";
if (lang == "ImgFile") {
_vue_RoundRobinOperate.round_robin.ImgFile = obj.fileUrl;
} else if (lang == "ImgFileTra") {
_vue_RoundRobinOperate.round_robin.ImgFileTra = obj.fileUrl;
} else if (lang == "ImgFileSimp") {
_vue_RoundRobinOperate.round_robin.ImgFileSimp = obj.fileUrl;
}

delete _vue_RoundRobinOperate.transmission_dataS[obj.packId];
}
else if (obj.type == 2) {
var transmission_data = _vue_RoundRobinOperate.transmission_dataS[obj.packId];
transmission_data.packIndex = obj.packIndex;
_vue_RoundRobinOperate.sendPack(2, transmission_data, lang);
}
}).catch(function (error) {
console.info(error);
setTimeout(function () {
_vue_RoundRobinOperate.uploadFile(pack, lang);
}, 5000);
});
},
readFile: function (lang) {
var file = this.imgList[lang];//input.files[0];
var query = {};
var chunks = [];
var chunk = 1 * 1024 * 1024;   //每片大小
if (!!file) {
this.error_tips[lang] = "";
var temp0 = file.name.split('.');
var _extension = temp0[temp0.length - 1];
var start = 0;
//文件分片
for (var i = 0, len1 = Math.ceil(file.size / chunk) ; i < len1 ; i++) {
var end = start + chunk;
chunks[i] = file.slice(start, end);
start = end;
}

var packid = parseInt(Math.random() * 10000) + new Date().getTime();
this.transmission_dataS[packid] = {
packCount: chunks.length,
packIndex: 0,
packId: packid,
dataExtension: _extension,
dataBuffer: chunks
};
//console.log("file.name -》");
this.temp_ImgFile[lang].progress = "開始上傳";
this.sendPack(0, this.transmission_dataS[packid], lang);
} else {
this.error_tips[lang] = "請選擇文件,然後再點上傳";
}
},
sendPack: function (type, transmission_data, lang) {
var reader = new FileReader();
reader.readAsDataURL(transmission_data.dataBuffer[transmission_data.packIndex]);
reader.onload = function (e) {
//Type_Count_Id_Index_Data_key_extension
//Type 0-包开始 1-包传输中 2-包结束
//key MD5(Type+Count+Id+Index)
var Count = transmission_data.packCount;
var Index = transmission_data.packIndex;
var Id = transmission_data.packId;
var data = this.result;
var Type = type;
var key = Type + Count + Id + Index;
var extension = transmission_data.dataExtension;
var pack = Type + "_" + Count + "_" + Id + "_" + Index + "_" + data + "_" + key + "_" + extension;
_vue_RoundRobinOperate.uploadFile(pack, lang);
}
}
}
});
});
</script>

c# 后台代码

//定义全局变量
public ActionResult index()
{
if (System.Web.HttpContext.Current.Cache["MyDictionary"] == null)
{
ConcurrentDictionary<string, List<MyDictionaryValueModel>> MyDictionary = new ConcurrentDictionary<string, List<MyDictionaryValueModel>>();
System.Web.HttpContext.Current.Cache["MyDictionary"] = MyDictionary;
}
return View();
}

#region 上傳
public class MyDictionaryValueModel
{
public string Id { get; set; }
public string[] Data { get; set; }
public int Index { get; set; }

}
public JsonResult uploadFile(string data)
{
//Type_Count_Id_Index_Data_key_extension
//Type 0-包开始 1-包传输中 2-包结束
//key MD5(Type+Count+Id+Index)
string temp_folder = string.Empty;
string upload_folder = CommonService.ConfigurationManagerService.RoundRobinManageFolder;
string root = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
try
{
string UserId = GeneralMethods.GetCurrent().LoginName;
var dataArry = data.Split('_');
if (dataArry.Length == 7)
{
string Type = dataArry[0],
Count = dataArry[1],
Id = dataArry[2],
Index = dataArry[3],
Data = dataArry[4],
key = dataArry[5],
extension = dataArry[6];
ConcurrentDictionary<string, List<MyDictionaryValueModel>> MyDictionary = (ConcurrentDictionary<string, List<MyDictionaryValueModel>>)System.Web.HttpContext.Current.Cache["MyDictionary"];
if (Type == "0")
{
if (!MyDictionary.ContainsKey(UserId))
{
MyDictionary.TryAdd(UserId, new List<MyDictionaryValueModel>());
}
MyDictionary[UserId].Add(new MyDictionaryValueModel { Id = Id, Data = new string[Convert.ToInt32(Count)], Index = 0 });
}

var ValueModel = MyDictionary[UserId].Where(d => d.Id == Id).FirstOrDefault();
ValueModel.Data[Convert.ToInt32(Index)] = "received";
//------ 把文件块 保存到临时文件夹
var btsdata = Convert.FromBase64String(Data.Split(',')[1]);
temp_folder = root + upload_folder + @"/"+Id;

if (!Directory.Exists(temp_folder))
{
Directory.CreateDirectory(temp_folder);
}
string file1 = temp_folder + @"/" + Index + "." + "temp";//文件块
using (FileStream fs = new FileStream(file1, FileMode.Create))
{
fs.Write(btsdata, 0, btsdata.Length);
fs.Close();
}
//------

if (Convert.ToInt32(Count) == 1 || Type == "2")
{
bool data_is_complete = true;
for (int i = 0, len = ValueModel.Data.Length; i < len; i++)
{
var tempdata = ValueModel.Data[i];
if (tempdata == null)
{
data_is_complete = false;
//通知客户端 重新发送丢失的包
return Json(new { type =2, packId =Id, packIndex =i}, JsonRequestBehavior.AllowGet);
}

}
if (data_is_complete)
{
string uploadDir = root + upload_folder;

if (!Directory.Exists(uploadDir))
{
Directory.CreateDirectory(uploadDir);
}
string file_name = upload_folder + @"/" + Guid.NewGuid().ToString("D") +"-"+ DateTime.Now.ToString("HHmmssfff") + "." + extension;
string file = root + file_name;
using (FileStream fs = new FileStream(file, FileMode.Create))
{//从临时文件夹,读取文件块,合并到同一个文件
for (int i = 0, len = Convert.ToInt32(Count); i < len; i++)
{
string file2 = temp_folder + @"/" + i.ToString() + "." + "temp";
var tempBytes = System.IO.File.ReadAllBytes(file2);
fs.Write(tempBytes, 0, tempBytes.Length);
}
fs.Close();
}
DeleteFolder(temp_folder);//删除临时文件
Directory.Delete(temp_folder, true);//删除临时文件夹

MyDictionary[UserId].Remove(ValueModel);
return Json(new { type = 1, packId = Id,fileUrl= file_name }, JsonRequestBehavior.AllowGet);
}
}
else
{
//通知客户端 已接收到
ValueModel.Index++;
return Json(new { type = 0, packId = Id ,packIndex = ValueModel.Index }, JsonRequestBehavior.AllowGet);
}
}
}
catch (Exception ex)
{
if (temp_folder != string.Empty)
{
DeleteFolder(temp_folder);
Directory.Delete(temp_folder, true);
}
//throw ex;
JsonResult result = new JsonResult();
result.MaxJsonLength = int.MaxValue;
result.Data = new { type = -1, message = ex.ToString() };
return result;
}
return Json(new { type = -1, message = "param error" }, JsonRequestBehavior.AllowGet);
}

public void DeleteFolder(string dir)
{
System.Threading.Tasks.Parallel.ForEach(Directory.GetFileSystemEntries(dir), (d) => {
try
{
if (System.IO.File.Exists(d))
{
FileInfo fi = new FileInfo(d);
if (fi.Attributes.ToString().ToLower().IndexOf("readonly") != -1)
fi.Attributes = FileAttributes.Normal;
System.IO.File.Delete(d);//直接删除其中的文件
}
else
{
DirectoryInfo d1 = new DirectoryInfo(d);
if (d1.GetFiles().Length != 0)
{
DeleteFolder(d1.FullName);////递归删除子文件夹
}
Directory.Delete(d);
}
}
catch
{

}
});
if (Directory.GetFileSystemEntries(dir).Length > 0)
{
DeleteFolder(dir);
}
}
#endregion

注:
1.websocket、signalr同理可得
2.注意文件分块,每块的大小,不适宜太大,会受到传输限制,上传失败时,可以尝试调整大小,目前设置的是每块1M
3.欢迎拍砖,反正我也不改

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐