Home >Backend Development >PHP Tutorial >php服务器端如何获得multipart/form-data post的json数据

php服务器端如何获得multipart/form-data post的json数据

WBOY
WBOYOriginal
2016-06-23 13:52:132579browse

客户端是用java post一个multipart/form-data请求,包含json参数数组,和一个上传的文件。
请问在php服务器端如何解析/获取json数据?


回复讨论(解决方案)

下面是java客户端代码 
   public void doPost() {
        Log.d(TAG, "======doHttpConnectionPost ");

        HttpURLConnection conn = null;
        DataOutputStream dos = null;
        InputStream in = null;
        try {
            StringBuilder paramStr = new StringBuilder("");
            Iterator i = mParam.keys();
            while(i.hasNext()) {
                String key = i.next();
                Log.d(TAG, "key :" + key + ", value : " + mParam.getString(key) );
                if (!(KEY_LOGFILE.equals(key))) {
                    if(paramStr.length()>0) {
                        paramStr.append("&");
                    }
                    paramStr.append(key);
                    paramStr.append("=");
                    try {
                        paramStr.append(URLEncoder.encode(String.valueOf(mParam.getString(key)),"utf-8"));
                    } catch (UnsupportedEncodingException e) {
                        paramStr.append(mParam.getString(key));
                    }
                }
            }

            if(mUrl.charAt(mUrl.length()-1) != '?') {
                mUrl = mUrl + "?";
            }
            mUrl = mUrl+paramStr;

            Log.d(TAG, "====mUrl: " + mUrl);
            URL url = new URL(mUrl);

            conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(HTTP_PARAM_TIMEOUT);
            conn.setConnectTimeout(HTTP_PARAM_TIMEOUT);
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Charset", CHARSET);
            conn.setRequestProperty("connection", "keep-alive");
            conn.setRequestProperty("Content-Type", multipart/form-data + ";boundary=" + BOUNDARY);

            dos = new DataOutputStream(conn.getOutputStream());
            Log.d(TAG, "====after open conn.getoutputstream");

            i = mParam.keys();
            Map files = new HashMap();
            while(i.hasNext()) {
                String key = i.next();
                if ((KEY_LOGFILE.equals(key))) {
                    Log.d(TAG, "key :" + key + ", value : " + mParam.getString(key) );
                    if (!TextUtils.isEmpty(mParam.getString(key))) {
                        files.put(key, new File(mParam.getString(key)));
                    }
                }
            }

            for (Map.Entry file : files.entrySet()) {
                if (file.getValue() != null && file.getValue().exists()) {
                    StringBuilder sb = new StringBuilder();
                    sb.append(PREFIX);
                    sb.append(BOUNDARY);
                    sb.append(LINEND);

                    sb.append("Content-Disposition: form-data; name=\"" + file.getKey()
                            + "\"; filename=\""+file.getValue().getName()+"\""+LINEND);
                    sb.append("Content-Type: application/octet-stream; charset="+CHARSET+LINEND);
                    sb.append("Content-Transfer-Encoding: 8bit" + LINEND);
                    sb.append(LINEND);
                    Log.d(TAG, sb.toString());

                    dos.write(sb.toString().getBytes());
                    InputStream is = new FileInputStream(file.getValue());
                    Log.d(TAG, "filevalue="+file.getValue());
                    byte[] bytes = new byte[1024];
                    int len = 0;
                    while((len = is.read(bytes)) != -1) {
                        dos.write(bytes, 0, len);
                        Log.d(TAG, "in read file"+len);
                    }
                    is.close();
                    dos.write(LINEND.getBytes());
                }
            }
            byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();
            dos.write(end_data);
            dos.flush();

            int res = conn.getResponseCode();
            Log.d(TAG, "res = " + res);
            if(res==200){
                in = conn.getInputStream();
                int ch;
                StringBuilder sb2 = new StringBuilder();
                while ((ch = in.read()) != -1)
                {
                    sb2.append((char) ch);
                }
                Log.d(TAG, "response entity string:" + sb2);
                mResponse = new JSONObject(sb2.toString());
            }else{
                Log.d(TAG, conn.getResponseCode()+conn.getResponseMessage());
                in = conn.getErrorStream();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (dos != null) {
                    dos.close();
                }
                if (conn != null) {
                    conn.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

file_put_contents('test.txt', print_r($_POST, 1));
看看 test.txt 中有什么

json数据用_POST获取不到吧

一切结论都在调查研究之后!

file_put_contents('test.txt', print_r($_POST, 1));
输出到test.txt文件里是空的。

有高手帮忙看看这个问题?

不行?你就
file_put_contents('test.txt', file_get_contents('php://input'));
看看 test.txt 中有什么

你客户端是 Java 的,谁没事会摹写一个替你做测试?
你说是 post 方式的,但 $_POST 无值。显然是你的客户端的问题!

上传文件的同时传几个数据不是很正常的应用吗?

这个multipart/form-data有关系。
不能用$_POST取到json数据。
这个不是客户端的问题,老大!同样的java代码其他的非php服务器是好使的。
你做过这种方式的上传吗?

这个问题对有点php经验的同学应该很简单吧,请帮助哈。
现在上传的文件是可以正常获取到,就是不知道如何获取json数据。

我让你
file_put_contents('test.txt', file_get_contents('php://input'));
看看 test.txt 中有什么
你做了吗?

老大,做了,里面没东西,我不是回复了吗

'php://input'获取不到multipart/form-data方式post的数据,你不知道吗?

你只回复说 file_put_contents('test.txt', print_r($_POST, 1)); 没有内容
并没有说  file_put_contents('test.txt', file_get_contents('php://input')); 没有内容

php://input 获取的是没有被 php 解析过的(或是说是 php 解析后剩余的输入流)

如果 php://input 也没有内容,那就一定是被 php 解析了
你可以在观察 $_FILES 是否有值,很可能你的数据被当做上传文件给处理了
不要总以为 json 有什么特殊性,对于网络传输而言,也就只不过是一个字符串而已。只要你发送了,就一定在数据流中
multipart/form-data 是 application/x-www-form-urlencoded 的特例
你也可以视为是 application/x-www-form-urlencoded 的扩展
凡是要用 http 协议上传文件,就一定要有 multipart/form-data 声明,并以他约定的方式组织数据

至于我是否做过上传文件,那么你可以在精华区找到前几年我参与的有关各种上传文件的方法的讨论
只是由于完全按照规范来写,的确没有失败的经验

file_put_contents('test.txt', file_get_contents('php://input'));
文件里也没有内容 ;-(

file_put_contents('test.txt', print_r($_FILES, 1));
总该有内容了吧?

file_put_contents('test.txt', print_r($_FILES, 1));
打印出来是这个:

Array
(
    [logFile] => Array
        (
            [name] => log.zip
            [type] => application/octet-stream
            [tmp_name] => /var/www/php7Ax336
            [error] => 0
            [size] => 28571
        )

)

嗯,这还是附加的数据没有命名的原因
php在解析post方式 数据时,会忽略 name="" 这一节的数据

为此用 curl 做了一下测试

$file = realpath('0.txt');$fields = array( 'f' => '@'.$file, '' => 'abcd', //没有名字就收不到,反之就可以收到);$ch = curl_init();  curl_setopt($ch, CURLOPT_URL,"http://localhost/ajax_server.php?id=1");  curl_setopt($ch, CURLOPT_POST, 1 );curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);curl_exec ($ch);  curl_close ($ch);  
但是数据是完整的传到了
--------------------------6e77d33195b440f3Content-Disposition: form-data; name="f"; filename="D:\\AMP\\web\\0.txt"Content-Type: application/octet-stream这是一个测试--------------------------6e77d33195b440f3Content-Disposition: form-data; name=""abcd--------------------------6e77d33195b440f3--

所以最好是与客户端的开发人员协商,给每个数据项都起个名字
当然你也可以用 php 来解决这个问题,那就是在 php.ini 中加上
enable_post_data_reading = Off
这就阻止了 php 解析 post 方式数据的动作
输入流就可以被 php://input 取到了
然后你再对读到的数据分类保存,你肯定比 php 勤快,不可能忽略掉没有名字的数据项了

注意:由于你阻止了 php 对 post 数据的解析额,所以 $_POST、$_FILES 都无效了!应用时切切注意

所以最好是与客户端的开发人员协商,给每个数据项都起个名字。
这个每个数据项都起个名字是啥意思?我post的数据:
http://api.hdtv.com/save?modelName=%E8%AE%BE%E7%BD%AE&type=S60&contact=777720&description=&version=V320R470C096B07166T&versionName=3.0.096T&model=S60&ui=3.0&hwVersion=H5001&mac=be60ebe15a7c

解决办法只能是修改php.ini吗?

我#17下部第7行 
Content-Disposition: form-data; name= ""
name 为空串,就是没有名字

找个人不也要喊名字吗?光喂喂喂的谁踩你?


你给的那个连接是什么意思?什么东西都不显示

大侠 您好,

我的name是有名字的啊?name=log.zip

那个链接是post数据的url,都有名字。

这个问题怎么解决,请问大侠?

你不是说:包含json参数数组,和一个上传的文件 吗?
打印 $_FILES 有
[logFile] => Array
        (
            [name] => log.zip
这个是有名字的,表示文件上传正确
打印 $_POST 是空的(#5)
表示那个 json 数据没有被接收到

你那个连接,一是没有任何显示,不知是否正确。而是看源码(不是很仔细),也没看到有上传或提交

再说那是 js 操作的页面,与 Java 有什么关系?

我的代码是手机上android的java上传,
你说js是什么意思?
有什么办法吗?大侠

这段java代码和其他服务器配合是没有问题的,
我现在是想在服务器端用php接收而已。
求大侠,高手帮助啊

这个问题找到原因了
http://api.hdtv.com/save?modelName=%E8%AE%BE%E7%BD%AE&type=S60&contact=777720&description=&version=V320R470C096B07166T&versionName=3.0.096T&model=S60&ui=3.0&hwVersion=H5001&mac=be60ebe15a7c
这个url里的参数是得用_GET去获取的,

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Previous article:php algorithmNext article:CI模板中php脚本的使用