问题描述:在ecmall个人用户登录,点击用户中心-店铺设置-更换店标,上传一个jpg图像(图像符合规范)后,不能预览,而且在页面底部点击提交后没有上传成功。banner店铺条幅也是一样的情况,还有下面的店铺简介中也无法上传图片。不光如此,上传了竟然还不能预览。

版本ecmall2.3.0

1.web上传文件原理

查看源码,发现ecmall上传文件是用JQuery+PHP的方式实现上传的,于是去搜这种方式的原理,解释如下。

首先明确,上传步骤是web浏览器先把文件传到服务器端,放在临时文件夹中的一个改了名字的临时文件,然后使用上传处理函数来把这个文件拷贝到其他地方。完成之后临时文件会被删除,所以如果不拷贝出来,就没了。这与使用PHP、JSP还是ASP哪种语言无关。把<input type="file" />放在form中,当form提交的时候,就传上去了。

以下是示例代码:

test.html

<form action="do_file_upload.php"method="post"enctype="multipart/form-data">

    <p>

        上传图片:

        <input type="file" name="picture" />

        <input type="submit" value="Send" />

    </p>

</form>

注意:enctype="multipart/form-data",必需这样设定,表示动作为文件上传。请求成功后,文件被上传到了服务器的临时文件夹中。至于到达目的地后,如果不转移出去,则在表单请求结束时会删除文件。所以我们要写一个处理上传文件的脚本,这里我们用PHP来处理

do_file_upload.php

<?php

$error="";//上传文件出错信息

$msg="";

$fileElementName='picture';

$allowType=array(".jpg",".gif",".png");//允许上传的文件类型

$num     = strrpos($_FILES['picture']['name'],'.');

$fileSuffixName   =substr($_FILES['picture']['name'],$num,8);//此数可变

$fileSuffixName   =strtolower($fileSuffixName);//确定上传文件的类型

$upFilePath            ='d:/';//最终存放路径

if(!empty($_FILES[$fileElementName]['error']))

{

switch($_FILES[$fileElementName]['error'])

{

case'1':

$error='传的文件超过了php.ini 中 upload_max_filesize选项限制的值';

break;

case'2':

$error='上传文件的大小超过了HTML 表单中 MAX_FILE_SIZE选项指定的值';

break;

case'3':

$error='文件只有部分被上传';

break;

case'4':

$error='没有文件被上传';

break;

case'6':

$error='找不到临时文件夹';

break;

case'7':

$error='文件写入失败';

break;

default:

$error='未知错误';

}

}elseif(empty($_FILES['fileToUpload']['tmp_name'])||$_FILES['fileToUpload']['tmp_name']=='none')

{

$error='没有上传文件.';

}elseif(!in_array($fileSuffixName,$allowType))

{

$error='不允许上传的文件类型';

}else{

$ok=@move_uploaded_file($_FILES['fileToUpload']['tmp_name'],$upFilePath); // move_uploaded_file函数把临时文件转移到目标路径下。

if($ok===FALSE){

$error='上传失败';

}

}

?>

另注:关于$_FILES数组

此数组包含有所有上传的文件信息,即记录下了上传文件时的相关信息。

以上范例中 $_FILES 数组的内容如下所示。我们假设文件上传字段的名称如上例所示,为 userfile。名称可随意命名。

$_FILES['userfile']['name']

客户端机器文件的原名称。

$_FILES['userfile']['type']

文件的 MIME 类型,如果浏览器提供此信息的话。一个例子是“image/gif”。不过此 MIME 类型在 PHP 端并不检查,因此不要想当然认为有这个值。

$_FILES['userfile']['size']

已上传文件的大小,单位为字节。

$_FILES['userfile']['tmp_name']

文件被上传后在服务端储存的临时文件名。

$_FILES['userfile']['error']

和该文件上传相关的错误代码。此项目是在 PHP 4.2.0 版本中增加的。

关于错误码

$_FILES['img']['error']有以下几种类型

UPLOAD_ERR_OK

其值为 0,没有错误发生,文件上传成功。

UPLOAD_ERR_INI_SIZE

其值为 1,上传的文件超过了 php.ini 中 upload_max_filesize选项限制的值。

UPLOAD_ERR_FORM_SIZE

其值为 2,上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。

UPLOAD_ERR_PARTIAL

其值为 3,文件只有部分被上传。

UPLOAD_ERR_NO_FILE

其值为 4,没有文件被上传。

UPLOAD_ERR_NO_TMP_DIR

其值为 6,找不到临时文件夹。PHP 4.3.10 和 PHP 5.0.3 引进。

UPLOAD_ERR_CANT_WRITE

其值为 7,文件写入失败。PHP 5.1.0 引进。

move_uploaded_file()

文件被上传后,默认地会被储存到服务端的默认临时目录中(除非 php.ini 中的 upload_tmp_dir设置为其它的路 径),文件名是随机的。如果该文件没有被移动到其它地方也没有被改名,则该文件将在表单请求结束时被删除。因此需要通过 move_uploaded_file移动临时文件。

经实验copy也能完成move_uploaded_file的功能,为啥要用move_uploaded_file呢?有说法是move_uploaded_file会对上传文件做一些检查,防止copy引起的一些安全漏洞。但具体copy会带来什么问题呢?我并没有查到。

安全检查

可以考虑通过$_FILES['img']['size']和$_FILES['img']['type']对上传的文件做一些安全检查,比如限定上传类型,上传文件的大小等。

2.解决问题

好了,经过对以上原理的了解,现在我们可以通过使用FireFox调试工具的方式,来跟踪图片上传的代码处理了。

F12打开FireFox调试窗口,在includes\libraries\javascript\ecmall.js中找到了function getFullPath(obj),在其内部打断点,一步一步运行。这个函数内没有异常,也正常获取到了上传图片的路径,是一窜看不懂的字符串。从这个函数跳出来后,就跳转到了themes\mall\default\my_store.index.html中的

$(function(){

$('input[ectype="change_store_logo"]').change(function(){//当点击上传logo图片按钮,上传了图片后,此动作被触发。

var src= getFullPath($(this)[0]);

$('img[ectype="store_logo"]').attr('src', src);

$('input[ectype="change_store_logo"]').removeAttr('name');

$(this).attr('name','store_logo');

});

看$('input[ectype="change_store_logo"]').change(function()这一行,这是JQuery语法,意思是图片选择控件发生内容变化的时候,就触发这个函数。它内部实现其实就是预览图片的功能,通过$('img[ectype="store_logo"]').attr('src', src);这一句代码实现。

从这个函数跳出后发现页面自己提交刷新了,貌似什么都没跟踪到,图片还是没上传。

通过前一节的分析,我们知道提交图片必须有个form,那么这个form是一定要被处理的,于是在form定义处发现

<formmethod="post" enctype="multipart/form-data"id="my_store_form">

没有指明处理form的PHP文件名称,说明这里使用JQuery处理的,于是在文件内搜索’# my_store_form’,终于找到了

$('#my_store_form').validate({

这行是当表单提交的时候,对数据做验证。断点进去,最后还是验证成功的,调用了其内部的

success       :function(label){

函数来输出校验成功标签。

到这里,说明客户端上传文件起码是成功的,问题会不会在服务器端没有保存文件,或者没有转移上传生成的临时文件呢?

再看那个JQuery的#my_store_form只是做了校验,但是我们前面说的,php服务器端对文件的转移工作呢?在哪里做的,线索到这里似乎断掉了,我不知道哪个php文件区处理了form。

于是又从头查起,根据MVC模式处理特点,先找到处理店铺设置的页面,是app\my_store.app.php。为了加快速度,直接去搜”上传文件“或者”上传图片“的字眼,发现了如下函数

/**

* 上传文件

*

*/

function _upload_files()

{

import('uploader.lib');

$data     =array();

/* store_logo */

$file=$_FILES['store_logo'];

if($file['error']==UPLOAD_ERR_OK&&$file!='')

{

$uploader=new Uploader();

$uploader->allowed_type(IMAGE_FILE_TYPE);

$uploader->allowed_size(SIZE_STORE_LOGO);//20KB

$uploader->addFile($file);

if($uploader->file_info()===false)

{

$this->show_warning($uploader->get_error());

returnfalse;

}

$uploader->root_dir(ROOT_PATH);

$data['store_logo']=$uploader->save('data/files/store_'.$this->_store_id.'/other','store_logo');

}

/* store_banner */

$file=$_FILES['store_banner'];

if($file['error']==UPLOAD_ERR_OK&&$file!='')

{

$uploader=new Uploader();

$uploader->allowed_type(IMAGE_FILE_TYPE);

$uploader->allowed_size(SIZE_STORE_BANNER);//200KB

$uploader->addFile($file);

if($uploader->file_info()===false)

{

$this->show_warning($uploader->get_error());

returnfalse;

}

$uploader->root_dir(ROOT_PATH);

$data['store_banner']=$uploader->save('data/files/store_'.$this->_store_id.'/other','store_banner');

}

return$data;

}

先在函数内加一行,用echo函数输出点字符信息,结果发现提交表单后,页面上头有字符打印。果然调用了这个函数,好幸运。

经过在几个异常分支加打印信息,发现

$uploader->addFile($file);

这行其实返回的是false,但是程序中没有对返回值判断,导致其溜掉了。进入其实现函数,是在includes\libraries\uploader.lib.php:23行,

/**

*    添加由POST上来的文件

*

*    @author   Garbin

*    @param   none

*    @return   void

*/

function addFile($file)

{

if (!is_uploaded_file($file['tmp_name']))

{

return false;

}

$this->_file = $this->_get_uploaded_info($file);

}

再加异常分支打印信息,发现is_uploaded_file函数返回false,看来对$file['tmp_name']的检测是失败的,会不会这个文件不存在?

于是回到my_store.app.php的_upload_files函数中,用var_dump($file);把$file的信息全部打印出来

array (size=5)

'name' =>string 'logo1.jpg' (length=9)

'type' =>string 'image/jpeg' (length=10)

'tmp_name' =>string 'D:\\xampp\\tmp\\phpA921.tmp' (length=27)

'error'

'size' => string '2512' (length=4)

临时文件的地址是一个实际机器上的地址,到这个地址下每一找到tmp文件,重试了多次,tmp文件的名称发生变化,但是均没生成文件。

到此,立刻觉得应该是这个目录没有写权限,于是给这个目录赋予了各种权限,连Everyone用户都是完全控制的权限赋予它,但是没用。网上搜这类问题,有说php.ini的临时文件配置不对,打开php.ini,看到upload_tmp_dir="D:\xampp\tmp",配置也没错。

后来还是在网上搜到,有人说是路径不能用两个反斜杠,应该替换成一个,于是试了下,把addFile中做如下替换

function addFile($file)

{

if (!is_uploaded_file(str_replace('\\\\','\\',$file['tmp_name'])))//把$file['tmp_name']中的\\换成\,这样本地路径才能访问。

{

return false;

}

$this->_file = $this->_get_uploaded_info($file);

}

竟然通过检查了,原来罪魁祸首在这里。我的php是5.4的,在这之前的版本是支持magic_quotes_gpc配置的,在php.ini中找到这一项,把它置为On,则PHP环境会自动对GET/POST/Cookie添加addslashes效果,会把返回路径两个斜杠过滤掉了,可惜5.4不支持了,现在我只能手动去替换字符了,不过也可以解决问题。

还没完,在uploader.lib.php中的save函数是用来拷贝临时文件到系统目录的,把这里return的地方也进行替换,如下

return $this->move_uploaded_file(str_replace('\\\\','\\',$this->_file['tmp_name']),$path);

问题解决,再在任何地方上传图片都OK了。

http://blog.csdn.net/socho/article/details/35566559

【ecmall】解决无法上传店铺logo和banner照片问题 (转)的更多相关文章

  1. 解决nginx上传模块nginx_upload_module传递GET参数

    解决nginx上传模块nginx_upload_module传递GET参数的方法总结 最近用户反映我们的系统只能上传50M大小的文件, 希望能够支持上传更大的文件. 很显然PHP无法轻易实现大文件上传 ...

  2. 解决phpmyadmin上传文件大小限制的配置方法(转)

    phpmyadmin导入SQL文件时涉及到phpmyadmin上传文件大小限制问题,默认phpmyadmin上传文件大小为2M,如果想要 phpmyadmin上传超过2M大文件,就需要修改phpmya ...

  3. 解决wordpress上传文件出现http错误问题

    解决wordpress上传文件出现http错误问题 问题现象 今天上传约1.4m大小的gif文件到wordpress的媒体库时失败,提示http错误. 原因 由于之前一直上传图片都是可以的,所以推测最 ...

  4. zt对于C#中的FileUpload解决文件上传大小限制的问题设置

    对于C#中的FileUpload解决文件上传大小限制的问题设置 您可能没意识到,但对于可以使用该技术上载的文件的大小存在限制.默认情况下,使用 FileUpload 控件上载到服务器的文件最大为 4M ...

  5. 解决phpmyadmin上传文件大小限制的配置方法

    解决phpmyadmin上传文件大小限制的配置方法 phpmyadmin导入SQL文件时涉及到phpmyadmin上传文件大小限制问题,默认phpmyadmin上传文件大小为2M,如果想要phpmya ...

  6. 解决文件上传插件Uploadify在火狐浏览器下,Session丢失的问题

    因为在火狐浏览器下Flash发送的请求不会带有cookie,所以导致后台的session失效. 解决的方法就是手动传递SessionID到后台. $("#fileresultfiles&qu ...

  7. iOS移动下上传图片失败解决 (上传多图,带其他参数)

    项目中有一个主要的功能,就是上传图片,结结果移动真的是很奇怪,WiFi,联通,电信都没有问题的情况下,居然在移动下不行,真的是很头疼.不过好在最后是解决了 项目的网络请求我是采用ASIHttpRequ ...

  8. 解决wordpress上传的文件尺寸超过 php.ini 中定义的 upload_max_filesize 值。

    上传的文件尺寸超过 php.ini 中定义的 upload_max_filesize 值. 解决方法:修改/etc/php5/apache2/php.ini文件中的 post_max_size = 6 ...

  9. 解决swfupload上传控件文件名中文乱码问题 三种方法 flash及最新版本11.8.800.168

    目前比较流行的是使用SWFUpload控件,这个控件的详细介绍可以参见官网http://demo.swfupload.org/v220/index.htm 在使用这个控件批量上传文件时发现中文文件名都 ...

随机推荐

  1. iOS日常学习 - iOS10上关于NSPhotoLibraryUsageDescription等问题

    最近升级了Xcode8.0,真是很多坑啊,填完一个来另外一个,今天又遇到了一个,用Xcode8.0上传项目时被驳回说是info.plist里面没有设置NSPhotoLibraryUsageDescri ...

  2. struts2——文件下载自定义文件名,包括中文

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  3. lua笔记之userdata

    1.一直使用框架里封装好的c库,想着自己一点一点的写些例子,学习下,以后需要c库,可以自己写了. 下边是一个简单的userdata的例子--数组操作. newarray.c #include &quo ...

  4. dataframe 列名重新排序

    在用list包含多个dict的模式生成dataframe时,由于dict的无序性,而uci很多数据的特征名直接是1,2,3...,生成的dataframe和原生的不一样, 为了方便观看和使用,我们将其 ...

  5. Ubuntu下MongoDB的安装

    一.MongoDB介绍 MongoDB 是一个是一个基于分布式文件存储的数据库,介于关系数据库和非关系数据库之间,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类似jso ...

  6. nrm npm源管理利器

    nrm npm源管理利器 nrm是管理npm源的一个利器. 有时候我们用npm install 安装依赖时会非常的慢,是官方自身的npm本来就慢,然后我们会尝试安装淘宝的npm或者cnpm,这些安装切 ...

  7. xpath选择器简介及如何使用

    xpath选择器简介及如何使用 一.总结 一句话总结:XPath 的全称是 XML Path Language,即 XML 路径语言,它是一种在结构化文档(比如 XML 和 HTML 文档)中定位信息 ...

  8. python 爬虫001-http请求过程

    HTTP 请求流程 一次完整的HTTP请求过程从TCP三次握手建立连接成功后开始,客户端按照指定的格式开始向服务端发送HTTP请求,服务端接收请求后,解析HTTP请求,处理完业务逻辑,最后返回一个HT ...

  9. 【河南第十届省赛-B】情报传递

    题目描述 抗日战争时期,在国共合作的大背景下,中共不断发展壮大,其情报工作也开始由获取警报性.保卫性信息,向获取军政战略性情报转变.各系统情报组织遵循"荫蔽精干,长期埋伏,积蓄力量,以待时机 ...

  10. 【第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛-J】 强迫症的序列

    小A是一个中度强迫症患者,每次做数组有关的题目都异常难受,他十分希望数组的每一个元素都一样大,这样子看起来才是最棒的,所以他决定通过一些操作把这个变成一个看起来不难受的数组,但他又想不要和之前的那个数 ...