后端技术
.net code 官方文档 https://docs.microsoft.com/zh-cn/aspnet/core/mvc/models/file-uploads?view=aspnetcore-3.1
上传方式:multipart/form-data
其他参数:Name,Version,Type
方法1:自定义解析
[ApiController] [Route("api/[controller]")] public class UploadController : ControllerBase { private const string fileRootPath = "D://files"; [HttpPost] [DisableFormValueModelBinding] [Route("UploadFile")] public async Task<ApiResult<FileUploadResponse>> UploadFile() { FileUploadResponse datas = new FileUploadResponse(); var reader = new MultipartReader(HeaderUtilities.RemoveQuotes((MediaTypeHeaderValue.Parse(Request.ContentType)).Boundary).Value, HttpContext.Request.Body); MultipartSection section = await reader.ReadNextSectionAsync(); while (section != null) { try { if (!ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition) || contentDisposition == null || !contentDisposition.DispositionType.Equals("form-data")) { continue; } using (var memoryStream = new MemoryStream()) { await section.Body.CopyToAsync(memoryStream); string fileName = contentDisposition.FileName.Value; string name = contentDisposition.Name.Value; if (string.IsNullOrWhiteSpace(fileName)) { var encoding = GetEncoding(section); string value = encoding.GetString(memoryStream.ToArray()); datas.Propertys.Add(new KeyValuePair<string, string>(name, value)); continue; } fileName = Guid.NewGuid().ToString("N") + Path.GetExtension(fileName); datas.FileNames.Add(fileName); using (var targetStream = System.IO.File.Create(Path.Combine(fileRootPath, fileName))) { await targetStream.WriteAsync(memoryStream.ToArray()); } } } finally { section = await reader.ReadNextSectionAsync(); } } return ResultState.Success(datas); }
}
移除.netCode默认
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class DisableFormValueModelBindingAttribute : System.Attribute, IResourceFilter { public void OnResourceExecuting(ResourceExecutingContext context) { var factories = context.ValueProviderFactories; factories.RemoveType<FormValueProviderFactory>(); factories.RemoveType<FormFileValueProviderFactory>(); factories.RemoveType<JQueryFormValueProviderFactory>(); } public void OnResourceExecuted(ResourceExecutedContext context) { }
}
返回值模型类
public class FileUploadResponse { public List<KeyValuePair<string, string>> Propertys { get; set; } = new List<KeyValuePair<string, string>>(); public List<string> FileNames { get; set; } = new List<string>(); }
方法二:使用IFormFile
[ApiController] [Route("api/[controller]")] public class UploadController : ControllerBase { private const string fileRootPath = "D://files"; [HttpPost] [Route("UploadFiles")] public async Task<ApiResult<FileUploadResponse>> UploadFiles([FromForm]FileUploadRequest data) //(IFormFile file, [FromForm] string name, [FromForm] string version, [FromForm] FileUploadType type) //([FromForm]List<IFormFile> files, [FromForm]string name) { var result = new FileUploadResponse(); result.Propertys.Add(new KeyValuePair<string, string>("Name", data.Name)); result.Propertys.Add(new KeyValuePair<string, string>("Version", data.Version)); result.Propertys.Add(new KeyValuePair<string, string>("Type", data.Type)); string suffix = Path.GetExtension(data.File.FileName); string fileName = data.File.FileName + "_" + Guid.NewGuid().ToString("N") + suffix; using (var stream = new FileStream(Path.Combine(fileRootPath, fileName), FileMode.Create)) { await data.File.CopyToAsync(stream); } result.FileNames.Add(fileName); return ResultState.Success(result); } }
请求模型类和返回值模型类
public class FileUploadRequest { public IFormFile File { get; set; } public string Name { get; set; } public string Version { get; set; } public string Type { get; set; } } public class FileUploadResponse { public List<KeyValuePair<string, string>> Propertys { get; set; } = new List<KeyValuePair<string, string>>(); public List<string> FileNames { get; set; } = new List<string>(); }
前端技术
前端采用vuex+element-ui
element-ui官网:https://element.eleme.cn/#/zh-cn/component/upload
方式1:el-upload action 提交
<template> <div> <el-form :model="form" :rules="rules" ref="form" label-width="150px"> <el-form-item label="名称" prop="name"> <el-input v-model="form.name" placeholder="请填写名称"/> </el-form-item> <el-form-item label="版本号" prop="version"> <el-input v-model="form.version" placeholder="请填写版本号"/> </el-form-item> <el-form-item label="类型" prop="type"> <el-input v-model="form.type" placeholder="请填写类型"/> </el-form-item> <el-form-item label="上传文件" prop="path"> <el-upload action="http://localhost:5001/api/FileUpload/UploadifyFile" :before-upload="beforeUpload" :show-file-list="false" :data="extraData()" :on-success="uploadSuccess" > <el-button size="small" type="primary">点击上传</el-button> <span>{{this.form.path}}</span> </el-upload> </el-form-item> </el-form> <br> </div> </template> <script> export default { data() { return { rules: { name: [ { required: true, message: "请填写名称", trigger: "blur" } ], version: [ { required: true, message: "请填写版本号", trigger: "blur" } ], type: [ { required: true, message: "请填写类型", trigger: "blur" } ], path: [ { required: true, message: "请选择文件", trigger: "blur" } ] }, form: { name: undefined, version: undefined, type: undefined, path: undefined } } }, methods: { extraData() { return { "name": this.form.name, "version": this.form.version, "type": this.form.type } }, uploadSuccess(response, file, fileList){ this.form.path = response.data.fileName; }, beforeUpload(file) { if(this.form.name == null || this.form.name === ""){ this.$message.error('请填写名称'); return false; } if(this.form.version == null || this.form.version === ""){ this.$message.error('请填写版本号'); return false; } if(this.form.type == null || this.form.type === ""){ this.$message.error('请填写类型'); return false; } return true; } } } </script>
方法二:axios提交
<template> <div> <el-form :model="form" :rules="rules" ref="form" label-width="150px"> <el-form-item label="名称" prop="name"> <el-input v-model="form.name" placeholder="请填写名称"/> </el-form-item> <el-form-item label="版本号" prop="version"> <el-input v-model="form.version" placeholder="请填写版本号"/> </el-form-item> <el-form-item label="类型" prop="type"> <el-input v-model="form.type" placeholder="请填写类型"/> </el-form-item> <el-form-item label="上传文件" prop="path"> <el-upload action="" :before-upload="beforeUpload" :show-file-list="false" :data="extraData()" :http-request="handleHttpRequest"> <el-button size="small" type="primary">点击上传</el-button> <span>{{this.form.path}}</span> </el-upload> </el-form-item> </el-form> <br> </div> </template> <script> import axios from "axios"; export default { data() { return { rules: { name: [ { required: true, message: "请填写名称", trigger: "blur" } ], version: [ { required: true, message: "请填写版本号", trigger: "blur" } ], type: [ { required: true, message: "请填写类型", trigger: "blur" } ], path: [ { required: true, message: "请选择文件", trigger: "blur" } ] }, form: { name: undefined, version: undefined, type: undefined, path: undefined } } }, methods: { extraData() { return { "name": this.form.name, "version": this.form.version, "type": this.form.type } }, handleHttpRequest(fileDatas){ var fd = new FormData(); for (let prop in fileDatas.data) { fd.append(prop, fileDatas.data[prop]); } fd.append("file", fileDatas.file); let config = { headers: { 'Content-Type': 'multipart/form-data' } } axios.post("http://localhost:5001/api/FileUpload/UploadifyFile", fd, config).then(response => { console.log(response); this.form.path = response.data.data.fileName; }); }, beforeUpload(file) { if(this.form.name == null || this.form.name === ""){ this.$message.error('请填写名称'); return false; } if(this.form.version == null || this.form.version === ""){ this.$message.error('请填写版本号'); return false; } if(this.form.type == null || this.form.type === ""){ this.$message.error('请填写类型'); return false; } return true; } } } </script>