一、需求
我们在用.net开发网站时,经常会用到图片上传,可以说是每个网站必备的,大到门户网站,电商网站,政务系统,OA系统,小到企业网站,个人网站,博客网站,导航网站等等,都有用到图片上传,那么在客户端浏览器中上传图片,不可避免有些不法分子将病毒伪装图片文件,然后上传到我们的网站服务器,这样造成网站崩溃。为了解决这个问题,我们在程序中先过滤,就有了接下来的文章。
二、主要代码
1、MVC中
我们就来上传一个头像,在MVC中怎么实现文件上传,请查看我的文章:【MVC系列】ASP.NET MVC中如何实现文件上传 FileUpLoad
/// <summary>/// 上传头像
/// </summary>
/// <param name="userId">用户编号</param>
/// <returns>Json(-1表示系统异常,-2表示文件不合法)</returns>
[HttpPost]
public JsonResult Upload(string userId)
{
//上传头像的路径
string folderPath = "/upload/avatar/";
//判断路径是否存在
if (!Directory.Exists(folderPath))
Directory.CreateDirectory(folderPath);//创建文件路径
HttpPostedFileBase uploadFile = Request.Files["avatars"];
if (uploadFile != null)
{
string oriFileName = uploadFile.FileName;//原始文件名
string fileName = userId + "_" + oriFileName;//文件名的格式:用户Id+文件名
uploadFile.SaveAs(Server.MapPath(folderPath + fileName));//保存到服务器
FileStream fs = new FileStream(Server.MapPath(folderPath + fileName), FileMode.Open, FileAccess.Read);
BinaryReader reader = new BinaryReader(fs);
string fileClass;
byte buffer;
byte[] b = new byte[2];
buffer = reader.ReadByte();
b[0] = buffer;
fileClass = buffer.ToString();
buffer = reader.ReadByte();
b[1] = buffer;
fileClass += buffer.ToString();
reader.Close();
fs.Close();
if (fileClass == "255216" || fileClass == "7173" || fileClass == "6677" || fileClass == "13780")
{
//255216是jpg;7173是gif;6677是BMP,13780是PNG;7790是exe,8297是rar
//Response.Write("图片可用");
//保存到数据库中
}
else
{
//Response.Write("图片非法");
FileInfo f = new FileInfo(Server.MapPath(folderPath + fileName));
f.Delete(); //删除文件
return Json(-2, JsonRequestBehavior.AllowGet);
}
return Json(Server.HtmlEncode(folderPath + fileName), JsonRequestBehavior.AllowGet);
}
return Json(-1, JsonRequestBehavior.AllowGet);
}
2、WebForm中
public void UploadFile() {try {
HttpPostedFile postfile = Request.Files["file"];
string savepath = Server.MapPath("/upload/avatar/" + postfile.FileName);
postfile.SaveAs(savepath);
FileStream fs = new FileStream(savepath, FileMode.Open, FileAccess.Read);
BinaryReader reader = new BinaryReader(fs);
string fileClass;
byte buffer;
byte[] b = new byte[2];
buffer = reader.ReadByte();
b[0] = buffer;
fileClass = buffer.ToString();
buffer = reader.ReadByte();
b[1] = buffer;
fileClass += buffer.ToString();
reader.Close();
fs.Close();
if (fileClass == "255216" || fileClass == "7173" || fileClass == "6677" || fileClass == "13780") {
//255216是jpg;7173是gif;6677是BMP,13780是PNG;7790是exe,8297是rar
//Response.Write("图片可用");
//保存到数据库中
}
else {
//Response.Write("图片非法");
File.Delete(savepath); //删除文件
return;
}
}
catch (Exception) { //Response.Write("图片非法!");
return;
throw;
}
}
三、总结
当然,这个只是防范病毒的一个很小的举措,技术不深奥,当然我这里写的过滤有个很大的缺陷,是先把文件上传上服务器,然后再检测,这样也不安全,可以在上传之前先检测,大家自己去实现哈。当然,上传文件要保证服务器的安全还有很多需要做的,比如在服务器中安装杀毒软件定时监测新增文件。还有硬件防火墙很多,在这里不再阐述。
在本章中如果在MVC中文件上传无从下手的同学,可以学习到文件上传,源码中采用swfupload上传,它可以支持多文件上传。具体实现请在文章末尾下载源代码。给大家布置一个作业,作进一步思考,怎么实现跨域或分布式上传文件。(作业的需求:网站文件服务器与Web服务器分离,用户上传文件的时候,我们把文件存取到文件服务器中,如果文件服务器磁盘已满,该作怎么处理?当然还有如果多用户同时上传文件,对磁盘写入,我们服务器配置无法满足现有的并发写入,我们需要考虑多文件服务器,多文件服务器,那么我们在上传文件又该做怎么处理呢?这里就涉及负载均衡和分布式)
大家有想法勇敢拍砖,欢迎拍砖,作业中的思考大家可以在评论中发表自己的看法。如果喜欢文章就顶我,也可以关注Me
结尾:这篇文章之前是发表在我的CSDN博客上的,把它移步到博客园来。CSDN的文章链接地址http://blog.csdn.net/naoguazi/article/details/8786400
最后附上全文件的源码:
Webform版比较简单就不上传了。
本文链接:http://www.cnblogs.com/naoguazi/p/MVC_Upload_File_Security.html,转载请注明。
本人菜鸟一枚,以下内容如有不当之处,劳烦指正。
本人由于想写个discuz插件,这个插件功能上涉及到上传文件这一功能,故以菜鸟的眼光来学习了下php上传文件。
首先,w3cshool查了下案例,觉得他说的非常详细,连我这个菜鸟都略懂了一二。
贴上地址:http://www.w3school.com.cn/php/php_file_upload.asp
照着这个讲解,写了下他这个demo,贴上代码:
html:
<label for="file">Filename:</label>
<input type="file" name="file" id="file">
<br/>
<input type="submit" name="submit" value="Submit"/>
</form>
这个表单页,作为php菜鸟的我说下我在这个里面学到的新东西:
1.form的属性enctype,百度翻译了下这个单词,才知道,这个是encode type 的缩写,就是指定往服务器传递信息的编码格式;
2.input的type属性file,这个专用文件上传的;
php:
//var_dump($_FILES);die;
if((($_FILES["file"]["type"]=="image/gif")||($_FILES["file"]["type"]=="image/jpeg")||($_FILES["file"]["type"]=="image/pjpeg")) && ($_FILES["file"]["size"]<100*1024*1024)){
if($_FILES["file"]["error"]>0){
echo "Error: ".$_FILES["file"]["error"]."<br/>";
}else{
echo "Upload: ".$_FILES["file"]["name"]."<br/>";
echo "Type: ".$_FILES["file"]["type"]."<br />";
echo "Size: ".($_FILES["file"]["size"]/1024)."Kb<br />";
echo "Stored in ".$_FILES["file"]["tmp_name"];
}
if(file_exists("upload/".$_FILES["name"]["name"])){
echo $_FILES["file"]["name"]."already exists.";
}else{
move_uploaded_file($_FILES["file"]["tmp_name"],"upload/".$_FILES["file"]["name"]);
echo "Stored in: "."upload/".$_FILES["file"]["name"];
}
}else{
echo "Invalid file";
}
关于调试这个demo的时候,我遇到一个问题:就是运行这个demo的时候php报出warning,表示上传不成功。
这个时候我就想打印出$_FILES这个变量来看看,结果打印出来发现error=1;才知道上传的文件超过了php.ini的上传文件大小,导致上传失败。
这里说下俺新了解的知识点:
$_FILES['myFile']['name'] 显示客户端文件的原名称。
$_FILES['myFile']['type'] 文件的 MIME 类型,例如"image/gif"。
$_FILES['myFile']['size'] 已上传文件的大小,单位为字节。
$_FILES['myFile']['tmp_name'] 储存的临时文件名,一般是系统默认。
$_FILES['myFile']['error'] 该文件上传相关的错误代码。以下为不同代码代表的意思:
0; 文件上传成功。
1; 超过了文件大小php.ini中即系统设定的大小。
2; 超过了文件大小
MAX_FILE_SIZE 选项指定的值。
3; 文件只有部分被上传。
4; 没有文件被上传。
5; 上传文件大小为0。
$result = null;
$uploadDir = './mail'; //上传路径
if(!submitcheck($_POST['formhash2'])){ //检测是否是上传文件
if($_POST['upname']==''){ //判断上传文件的命名是否为空
$result=lang('plugin/saya_mails', 'noname');
}else{
$myfile = $_FILES['myfile']; //获取上传的文件信息
$myfileType = substr($myfile['name'], strrpos($myfile['name'], ".") + 1); //两种获取上传文件?p>阅读更多内容
没有评论:
发表评论