2014年2月13日星期四

ASP.NET中上传图片检测其是否为真实的图片 防范病毒上传至服务器 - 脑瓜子

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
ASP.NET中上传图片检测其是否为真实的图片 防范病毒上传至服务器 - 脑瓜子  阅读原文»

一、需求

我们在用.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

最后附上全文件的源码:

MVC 版

Webform版比较简单就不上传了。


本文链接:http://www.cnblogs.com/naoguazi/p/MVC_Upload_File_Security.html,转载请注明。

【菜鸟学php】用菜鸟的眼光浅谈php上传文件 - phpdreamer  阅读原文»

本人菜鸟一枚,以下内容如有不当之处,劳烦指正。

本人由于想写个discuz插件,这个插件功能上涉及到上传文件这一功能,故以菜鸟的眼光来学习了下php上传文件。

首先,w3cshool查了下案例,觉得他说的非常详细,连我这个菜鸟都略懂了一二。

贴上地址:http://www.w3school.com.cn/php/php_file_upload.asp

照着这个讲解,写了下他这个demo,贴上代码:

html:

<form action="demo.php" method="post" enctype="multipart/form-data">
<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:

//echo phpinfo();
//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的上传文件大小,导致上传失败。

这里说下俺新了解的知识点:

  
  PHP编程语言中的常见的$_FILES 系统函数用法有
  
$_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。

到这里,应该就知道了我刚刚运行demo的错误是啥导致的,那既然发现是php.ini里面限制超出了,那接下来我就修改了下php.ini的配置。
总结下我修改这个php.ini上传限制的感受:
首先,要修改php上传文件大小限制,那要改php.ini里面的两个参数,一个是upload_max_filesize,还有个就是post_max_size,修改下这两个参数的大小就可以了!
其次,就是找准php.ini的位置,我由于本地电脑搭建的是集成环境,所以php.ini在apache文件夹下面,如果是自己搭建的环境,那就在php文件夹下面,如果找不到,echo下phpinfo(),可以看到php.ini文件的位置。
那到此为止,跟我差不多的新手们就能运行w3cshool上面的demo了,完成上传实例了。
关于上传文件,我看了下discuz其他插件作者开发的插件,有点小收获,贴上来跟大家分享下:
   $fileTypes = array('mp3','wav'); //定义允许上传的文件类型
$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>阅读更多内容

没有评论:

发表评论