如何实作上传档案功能
小明问说他要製作在网页中上传档案, 但不知道要怎么做?
提供使用者将档案上传到伺服器的能力时, 请务必小心. 因为攻击者可能会尝试
执行阻断服务的攻击上传病毒或恶意程式码以其他方式危害网路和伺服器降低成功攻击的可能性的安全性方法如下
将档案上传到专用的档案上传区域, 最好是在非系统磁碟机上. 并停用档案上传位置的 execute 许可权.请勿将上传的档案保存在与应用程式相同的目录树状结构中.使用应用程式所决定的安全档案名. 请勿使用使用者所提供的档案名称或不受信任档案名称.检查上传档案的大小, 设定最大大小限制以防止大量上传.当涉及到上传较大的档案时, 一般人总是认为直接修改Web 设定
maxRequestLength 和 maxAllowedContentLength 设定
这绝对不是正确的做法, 因为你总不可能无限制地加大Request 上传大小,
加大上传大小更容易受到阻断服务的攻击.
而且一次性上传大档案会遇到很多挑战, 例如UI 回应能力, 上传进度, 客户端必须再次上载等等.
在这种情况下, 最好分块上传大档案, 它具有很多优点, 例如
在这里我将展示如何以小块形式上传档案
首先在网页中输入以下内容
<input type="file" accept=".pdf,.png" onChange="fileUpload">
接着準备Javascript 程式码
<script>function fileUpload(sender) { var fileList = sender.currentTarget.files; var file = fileList[0]; chunky(file, 0);}function chunky(file, chunkIndex) { let chunkSize = 1024 * 4; let totalSize = file.size; let totalChunkSize = Math.floor((totalSize + chunkSize - 1) / chunkSize); if( chunkIndex >= totalChunkSize ) { return; } let start = chunkIndex * chunkSize; let blob = file.slice(start, start + chunkSize); var dataForm = new DataForm(); dataForm.append("fileUpload", blob, file.name); dataForm.append("chunkIndex", chunkIndex); dataForm.append("totalSize", totalSize); $.ajax({ url: "/Home/UploadFileChunk", type: "POST", processData: false, contentType: false data: dataForm }).done(function(r){ chunky(file, chunkIndex+1); });}</script>
在客户端将每个档案切成小块,每一块大小在 "chunkSize" 中指定, 您可以更改此大小.
Javascript 上传每个块, 然后等待其完成, 然后再开始上传下一个块.
以下是伺服器端的实作程式码
public class UploadRequest { public HttpPostedFileBase File { get; set } public int ChunkIndex { get; set; } public int TotalSize { get; set; }}public ActionResult UploadFileChunk(UploadRequest req) { var inputStream = req.File.InputStream; using(var fs=new FileStream("D:/tmp/customer.png", FileMode.Append, FileAccess.Write)) { var buffer = new byte[1024]; var readSize = inputStream.Read(buffer, 0, 1024); while (readSize > 0) { fs.Write(buffer, 0, readSize); readSize = inputStream.Read(buffer, 0, 1024); } fs.Flush(); fs.Close(); } return Json("OK");}
这只是个示範示意程式, 不是正式完整的程式码.
在伺服器端, 我们都接收到前端传送过来是一个单独的档案块, 将其保存到临时资料夹中,
每次收到档案块, 需要将它们合併回原始档案中.
所以我们需要输入三个参数(档案区块内容File, 块索引ChunkIndex, 原始档案的总共大小TotalSize)
你必须检查这三个参数内容是否合法.
最后我们需要注意以下几点
当 ChunkIndex == 0 的时候, 就建立全新的暂存档案当 ChunkIndex == 最后档案区块索引, 就相当于上传结束检查 ChunkIndex 索引值, File 大小是否在合理的範围内就是这样-祝您上传愉快!