목차
回复讨论(解决方案)
백엔드 개발 PHP 튜토리얼 php服务器端如何获得multipart/form-data post的json数据

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

Jun 23, 2016 pm 01:52 PM
json multipart php post 데이터

客户端是用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去获取的,

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

CakePHP 프로젝트 구성 CakePHP 프로젝트 구성 Sep 10, 2024 pm 05:25 PM

이번 장에서는 CakePHP의 환경 변수, 일반 구성, 데이터베이스 구성, 이메일 구성에 대해 알아봅니다.

Ubuntu 및 Debian용 PHP 8.4 설치 및 업그레이드 가이드 Ubuntu 및 Debian용 PHP 8.4 설치 및 업그레이드 가이드 Dec 24, 2024 pm 04:42 PM

PHP 8.4는 상당한 양의 기능 중단 및 제거를 통해 몇 가지 새로운 기능, 보안 개선 및 성능 개선을 제공합니다. 이 가이드에서는 Ubuntu, Debian 또는 해당 파생 제품에서 PHP 8.4를 설치하거나 PHP 8.4로 업그레이드하는 방법을 설명합니다.

CakePHP 날짜 및 시간 CakePHP 날짜 및 시간 Sep 10, 2024 pm 05:27 PM

cakephp4에서 날짜와 시간을 다루기 위해 사용 가능한 FrozenTime 클래스를 활용하겠습니다.

CakePHP 데이터베이스 작업 CakePHP 데이터베이스 작업 Sep 10, 2024 pm 05:25 PM

CakePHP에서 데이터베이스 작업은 매우 쉽습니다. 이번 장에서는 CRUD(생성, 읽기, 업데이트, 삭제) 작업을 이해하겠습니다.

CakePHP 파일 업로드 CakePHP 파일 업로드 Sep 10, 2024 pm 05:27 PM

파일 업로드 작업을 위해 양식 도우미를 사용할 것입니다. 다음은 파일 업로드의 예입니다.

CakePHP 라우팅 CakePHP 라우팅 Sep 10, 2024 pm 05:25 PM

이번 장에서는 라우팅과 관련된 다음과 같은 주제를 학습하겠습니다.

CakePHP 토론 CakePHP 토론 Sep 10, 2024 pm 05:28 PM

CakePHP는 PHP용 오픈 소스 프레임워크입니다. 이는 애플리케이션을 훨씬 쉽게 개발, 배포 및 유지 관리할 수 있도록 하기 위한 것입니다. CakePHP는 강력하고 이해하기 쉬운 MVC와 유사한 아키텍처를 기반으로 합니다. 모델, 뷰 및 컨트롤러 gu

CakePHP 유효성 검사기 만들기 CakePHP 유효성 검사기 만들기 Sep 10, 2024 pm 05:26 PM

컨트롤러에 다음 두 줄을 추가하면 유효성 검사기를 만들 수 있습니다.

See all articles