后端服务使用的是Asp.net WebApi,至于如果有环境搭建或者怎么引入上传控件这一类的问题,请自行百度,都有手册多看几遍。
在此记录的是核心的一些代码,没有给出界面UI,因为重点是给出思路和怎么用
1.页面引入nz-upload
1.我们在Angular页面引入控件,主要介绍2个重要的属性,其他的建议读下手册
- 1.1. nzFileList的值就是双向绑定的文件列表,就是最终需要传到后端的,你如果需要展示那也可以取这里的值
- 1.2. nzBeforeUpload 一定要使用
箭头函数
,箭头函数
,箭头函数
,不要问为什么重复,踩过坑的,上传之前执行的事件
<nz-upload [nzAction]="''" [(nzFileList)]="fileList" nzMultiple [nzLimit]="0" [nzShowUploadList]="false"
[nzBeforeUpload]="beforeUpload">
<button [disabled]="false" nz-button nzType="primary" nz-popover nzPopoverContent="Upload File">
<i nz-icon nzType="upload"></i>
</button>
</nz-upload>
2.钩子事件和上传事件
1.钩子事件
就是上传事件之前执行的事件,可以做一些校验等操作,当然你也可以写在上传事件中,随处可见的AOP
fileList: NzUploadFile[] = [];
beforeUpload = (file: NzUploadFile): boolean => {
//判断文件大小
const isLt4M = file.size! / 1024 / 1024 < 4;
if (!isLt4M) {
this.message.error('Message.File.SizeFile');
return false;
}
this.fileList = this.fileList.concat(file);
return true;
}
2.上传事件
用于将文件信息提交到后端
async handleUpload() {
const formData = new FormData();
//将文件绑定到FormData中
this.fileList.forEach((file: any) => {
formData.append("files[]", file);
});
//给后端文件服务标识来源于什么系统
formData.append("system", "OA");
//给后端文件服务标识是什么类型的附件
formData.append('annexType', "附件类型");
//使用Post调用文件服务
this.httpclient.post<any>("192.168.0.105/api/FileServer/UploadFile", formData).toPromise();
}
3.下载文件
1.定义下载对象,然后调用后端下载api接口
downLoadFile(file: Attachment): void {
const DownloadRequest = {
FileFullPath: 文件服务器摘要返回的文件路径,
FileId: 文件服务器摘要返回的文件ID,
FullFileName: 文件服务器摘要返回的文件名称,
};
let head = new HttpHeaders({ 'Content-Type': 'application/json' });
//调用文件下载服务
this.httpclient.post<any>("192.168.0.105/api/FileServer/DownloadFile",DownloadRequest,{ headers: head, responseType: 'arraybuffer' }).subscribe(
(result) => {
if ('msSaveOrOpenBlob' in navigator) {
const nav = window.navigator as any;
nav.msSaveOrOpenBlob(
new Blob([]),
DownloadRequest.FullFileName
);
return;
} else {
const url = window.URL.createObjectURL(new Blob([result]));
const link = document.createElement('a');
link.style.display = 'none';
link.href = url;
link.setAttribute('download', DownloadRequest.FullFileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
return url;
}
})
4.后端WebAPI服务
-
在这里实现思路为文件服务器保存文件,并生成文件一对一的
摘要信息
,返回到客户端,客户端收到上传成功的摘要信息,然后将摘要Id
与业务数据绑定,存到业务数据库,下次加载数据,根据摘要Id
来找到对应的文件信息,然后访问文件服务器下载文件。 -
这里暂时不考虑,如果多个文件是否完整上传,中间有失败的情况,为了服务器安全,后端和前端应适当过滤筛选出一些不能被上传的文件后缀,例如DLL exe这些,这只是个小建议,当然您可以使用,你所喜欢的任何文件服务中间件,作为你的文件服务器
3.控制器中接收文件上传内容,存入本地磁盘文件夹,然后返回文件信息的摘要
包含如下
- 文件对应生成的唯一id
- 文件存储文件夹路径
- 文件内容长度
- 文件后缀名
- 文件是否被压缩
控制器接收
[HttpPost]
[Route("api/FileServer/UploadFile")]
public HttpResponseMessage UploadFile()
{
HttpRequest httpRequest = HttpContext.Current.Request;
string config = httpRequest.Params["system"].Trim();
string annexType = httpRequest.Params["annexType"].Trim();
if (string.IsNullOrEmpty(config) || string.IsNullOrEmpty(annexType))
{
return Request.CreateResponse(HttpStatusCode.BadRequest, "config and annexType is required.");
}
string FilePath = ConfigurationManager.AppSettings[config];
var filePath = HttpContext.Current.Server.MapPath(FilePath + annexType) + "\\";
if (!Directory.Exists(filePath)) Directory.CreateDirectory(filePath);
return UploadFileHandler(httpRequest,filePath);
}
文件处理方法
[NonAction]
public HttpResponseMessage UploadFileHandler(HttpRequest httpRequest, string filePath)
{
try
{
HttpResponseMessage result = null;
if (httpRequest.Files.Count > 0)
{
//文件信息的摘要
List<FileData> ResponseData = new List<FileData>();
for (int i = 0; i < httpRequest.Files.Count; i++)
{
FileData fileData = new FileData();
var postedFile = httpRequest.Files[i];
string guid = Guid.NewGuid().ToString().ToUpper();
//一个一个文件保存到本地磁盘
postedFile.SaveAs(filePath + guid);
fileData.FileId = guid;
fileData.FullFileName = postedFile.FileName;
fileData.FileFullPath = filePath + guid;
fileData.ContentLength = postedFile.ContentLength;
fileData.Extension = postedFile.FileName.Substring(postedFile.FileName.LastIndexOf('.'));
fileData.isZipFile = false;
ResponseData.Add(fileData);
}
result = Request.CreateResponse(HttpStatusCode.Created, ResponseData);
}
else
{
result = Request.CreateResponse(HttpStatusCode.BadRequest);
}
return result;
}
catch (Exception e)
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
response.ReasonPhrase = e.Message;
return response;
}
}
2.下载文件服务
[HttpPost]
[Route("api/FileServer/DownloadFile")]
public HttpResponseMessage DownloadFile(DownloadRequest request)
{
try
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
System.IO.FileInfo fileInfo = new System.IO.FileInfo(request.FileFullPath);
if (!fileInfo.Exists)
{
response = new HttpResponseMessage(HttpStatusCode.NotFound);
response.ReasonPhrase = "File does not exists.";
return response;
}
FileStream stream = new FileStream(request.FileFullPath, FileMode.Open);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/force-download");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = HttpUtility.UrlEncode(request.FullFileName)
};
response.Headers.Add("Access-Control-Expose-Headers", "FileName");
response.Headers.Add("FileName", HttpUtility.UrlEncode(request.FullFileName));
return response;
}
catch (Exception e)
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
response.ReasonPhrase = e.Message;
return response;
}
}