尝试从客户端使用Slim框架读取Json和图像文件

问题描述:

因此,我有一个客户端移动的请求与retrofit2和请求我需要发送图像文件和json对象。就像这样:尝试从客户端使用Slim框架读取Json和图像文件

RequestBody requestJson = RequestBody.create(MediaType.parse("application/json"), new Gson().toJson(cidadao)); 

      MultipartBody.Part fotoBody = MultipartBody.Part.createFormData("foto", file.getName(), requestFile); 
      MultipartBody.Part jsonBody = MultipartBody.Part.createFormData("cidadao", null, requestJson); 

      Service service = CallService.createService(Service.class); 
      Call<Void> cadastrarCidadao = service.postCidadao(UsuarioApplication.getInstance().getToken().getToken(), 
        jsonBody, 
        fotoBody); 
      cadastrarCidadao.enqueue(new Callback<Void>() { 
       @Override 
       public void onResponse(Call<Void> call, Response<Void> response) { 
        if (response.isSuccessful()) { 
         if (response.code() == 201) { 
          dialog.dismiss(); 
          FragmentManager fm = getFragmentManager(); 
          fm.popBackStack(); 
         } 
        } else { 
         APIError error = ErrorUtils.parseError(response); 
         new Throwable(error.getMessage()); 
        } 
       } 

       @Override 
       public void onFailure(Call<Void> call, Throwable t) { 
        Log.e("ErrorCadastro", t.getLocalizedMessage()); 
        Toasty.error(getContext(), "Erro na conexão").show(); 
       } 
      }); 

服务接口:

package com.example.administrador.citycaremobile.Services; 

import com.example.administrador.citycaremobile.Modelo.Cidadao; 
import com.example.administrador.citycaremobile.Modelo.Login; 

import okhttp3.MultipartBody; 
import okhttp3.RequestBody; 
import retrofit2.Call; 
import retrofit2.http.Body; 
import retrofit2.http.GET; 
import retrofit2.http.Header; 
import retrofit2.http.Headers; 
import retrofit2.http.Multipart; 
import retrofit2.http.POST; 
import retrofit2.http.PUT; 
import retrofit2.http.Part; 

public interface Service { 

@POST("cidadao/cadastrar") 
@Multipart 
Call<Void> postCidadao(@Header("X-Token") String token, 
         @Part MultipartBody.Part cidadao, 
         @Part MultipartBody.Part foto); 

@PUT("cidadao/put") 
Call<Boolean> putUsuario(@Header("Content-type") String content, 
         @Header("X-Token") String token, 
         @Body Cidadao cidadao); 

@Headers("content-type:application/json") 
@GET("auth") 
Call<Token> autentication(); 

//Login 
@POST("login") 
Call<Object> login(@Header("Content-type") String content, 
        @Header("X-Token") String token, 
        @Body Login login); 
} 

而在服务方面,有修身框架PHP,问题是...当我尝试获得JSON,用$请求 - > getParam(),它们返回给我一个包含所有字符的数组,其中每个字符都是该数组上的一个项目。例如,如果显示返回$ jsonParam [0],他向我返回“{”,我尝试将所有数组解析为一个String,但未使用,尝试了implode方法,尝试了param上的json_decode,但没有任何工作。

有服务端的方法:

$app -> post('/cidadao/cadastrar', function(Request $request, Response $response) use ($app){ 
     //Container do EntityManager 
     $entityManager = $this -> get('em'); 
     $json = $request -> getParam('cidadao'); 

     try{ 
      //Instância da entidade Login 
      $login = new Login(); 
      //recuperando o parâmetro objeto login do json 
      $fk_login_cidadao = $json['fk_login_cidadao']; 
      //setando valores do objeto login 
      $login ->setLogin($fk_login_cidadao['login']); 
      $login ->setEmail($fk_login_cidadao['email']); 
      $login ->setSenha($fk_login_cidadao['senha']); 
      $login ->setStatus_login($fk_login_cidadao['status_login']); 
      $login ->setAsAdministrador($fk_login_cidadao['administrador']); 

      //salvando login 
      $entityManager->persist($login); 
      $entityManager->flush(); 
      //buscando login recém salvo 
      $loginRepository = $entityManager->getRepository('App\Models\Entity\Login'); 
      //pegando login 
      $loginCidadao = $loginRepository->find($login->getId_login()); 
      //Salvar foto 
      $files = $request->getUploadedFiles(); 
      $newimage = $files['foto']; 
      if ($newimage->getError() === UPLOAD_ERR_OK) { 
       $uploadFileName = $newimage->getClientFilename(); 
       $type = $newimage->getClientMediaType(); 
       $name = uniqid('img-' . date('d-m-y') . '-'); 
       $name .= $newimage->getClientFilename(); 
       // $imgs[] = array('url' => '/Photos/' . $name); 
       //local server 
       $newimage->moveTo("/home/citycare/public_html/Imgs/user/$name");#/home/citycare/Imgs/User/$name 
       //localdev 
       $photoURL = "/home/citycare/public_html/Imgs/user/$name";#/home/citycare/Imgs/User/$name 
      } 
      //Instância da entidade Cidadao 
      $cidadao = new Cidadao(); 
      //setando valores do objeto cidadao 
      $cidadao ->setFk_login_cidadao($loginCidadao); 
      $cidadao->setNome($request->getParam('nome')); 
      $cidadao->setSexo($request->getParam('sexo')); 
      $cidadao ->setSobrenome($request->getParam('sobrenome')); 
      $cidadao ->setEstado($request->getParam('estado')); 
      $cidadao ->setCidade($request->getParam('cidade')); 
      $cidadao ->setDir_foto_usuario($request->getParam($photoURL)); 
      $entityManager->persist($cidadao); 
      $entityManager->flush(); 
      //retornando confirmação do evento completo 
      $return = $response->withStatus(201)->withHeader('Content-type', 'application/json'); 


     } catch (Exception $ex){ 
      //código e mensagem do erro 
      throw new Exception($ex->getMessage(), $ex->getCode()); 
     } 
     return $return; 
}); 

的图像处理工作正常。

HTTP REQUEST:

10-14 03:35:38.772 19151-9871/com.example.administrador.citycaremobile D/OkHttp: --> POST http://servico.projetocitycare.com.br/cidadao/cadastrar http/1.1 
10-14 03:35:38.773 19151-9871/com.example.administrador.citycaremobile D/OkHttp: Content-Type: multipart/form-data; boundary=58c96b8f-a56e-4b42-8052-10d48c583cc4 
10-14 03:35:38.776 19151-9871/com.example.administrador.citycaremobile D/OkHttp: Content-Length: 69178 
10-14 03:35:38.777 19151-9871/com.example.administrador.citycaremobile D/OkHttp: X-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoicm9vdCIsInNlbmhhIjoiY2FyZWNpdHkiLCJleHAiOjE1MDc5NjMwOTUsImlwIjoiMTc3LjM3LjIyOC4xNDIifQ.ePeHn_YgmRfach6B1v4JC75147ixRwrjdoUvEjpPKRQ 
10-14 03:35:38.788 19151-9871/com.example.administrador.citycaremobile D/OkHttp: --58c96b8f-a56e-4b42-8052-10d48c583cc4 
10-14 03:35:38.788 19151-9871/com.example.administrador.citycaremobile D/OkHttp: Content-Disposition: form-data; name="cidadao" 
10-14 03:35:38.788 19151-9871/com.example.administrador.citycaremobile D/OkHttp: Content-Type: application/json; charset=utf-8 
10-14 03:35:38.788 19151-9871/com.example.administrador.citycaremobile D/OkHttp: Content-Length: 239 
10-14 03:35:38.788 19151-9871/com.example.administrador.citycaremobile D/OkHttp: {"cidade":"Alto Rio Novo","estado":"Espírito Santo","fk_login_cidadao":{"administrador":false,"email":"[email protected]","login":"kddjsjn","senha":"jskeieej","status_login":true},"nome":"neenenem","sexo":"Masculino","sobrenome":"memekekk"} 
10-14 03:35:38.788 19151-9871/com.example.administrador.citycaremobile D/OkHttp: --58c96b8f-a56e-4b42-8052-10d48c583cc4 
10-14 03:35:38.788 19151-9871/com.example.administrador.citycaremobile D/OkHttp: Content-Disposition: form-data; name="foto"; filename="cropped83912673.jpg" 
10-14 03:35:38.788 19151-9871/com.example.administrador.citycaremobile D/OkHttp: Content-Type: multipart/form-data 
10-14 03:35:38.788 19151-9871/com.example.administrador.citycaremobile D/OkHttp: Content-Length: 68558 
10-14 03:35:38.788 19151-9871/com.example.administrador.citycaremobile D/OkHttp: ������JFIF����������������C�� 
10-14 03:35:38.800 19151-9871/com.example.administrador.citycaremobile D/OkHttp: --58c96b8f-a56e-4b42-8052-10d48c583cc4-- 
10-14 03:35:38.800 19151-9871/com.example.administrador.citycaremobile D/OkHttp: --> END POST (69178-byte body) 

HTTP RESPONSE:

10-14 03:35:39.675 19151-9871/com.example.administrador.citycaremobile D/OkHttp: <-- 500 Internal Server Error http://servico.projetocitycare.com.br/cidadao/cadastrar (874ms) 
10-14 03:35:39.676 19151-9871/com.example.administrador.citycaremobile D/OkHttp: Server: nginx 
10-14 03:35:39.676 19151-9871/com.example.administrador.citycaremobile D/OkHttp: Date: Sat, 14 Oct 2017 06:35:39 GMT 
10-14 03:35:39.676 19151-9871/com.example.administrador.citycaremobile D/OkHttp: Content-Type: application/json;charset=utf-8 
10-14 03:35:39.677 19151-9871/com.example.administrador.citycaremobile D/OkHttp: Transfer-Encoding: chunked 
10-14 03:35:39.677 19151-9871/com.example.administrador.citycaremobile D/OkHttp: Connection: keep-alive 
10-14 03:35:39.678 19151-9871/com.example.administrador.citycaremobile D/OkHttp: Upgrade: h2,h2c 
10-14 03:35:39.685 19151-9871/com.example.administrador.citycaremobile D/OkHttp:  {"message":"An exception occurred while executing 'INSERT INTO login (email, login, senha, status_login, administrador) VALUES (?, ?, ?, ?, ?)' with params [\"{\", \"{\", \"ew==\", \"{\", \"{\"]:\n\nSQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '{' for key 'UNIQ_AA08CB10E7927C74'"} 
10-14 03:35:39.686 19151-9871/com.example.administrador.citycaremobile D/OkHttp: <-- END HTTP (310-byte body) 

的Json sended是这样的:

{"cidade":"Brasília", 
    "estado":"Distrito Federal", 
    "fk_login_cidadao":{ "administrador":false, 
          "email":"[email protected]", 
          "login":"jhon", 
          "senha":"182873728192", 
          "status_login":true}, 
    "nome":"Jhon", 
    "sexo":"Masculino", 
    "sobrenome":"James"} 
+0

我需要看看你的postCadadao函数和接口代码。将其添加到问题中。谢谢。 – Scriptonomy

+0

上升。功能代码从改造后运行,所以我只是实现与服务的接口。 –

+0

我需要看看您的请求,发送请求到https://requestb.in/14i0kfg1并在此处留言。 – Scriptonomy

因此,经过多次尝试,在$ json上使用var_dump()我看到请求没有被框架解码,我不知道为什么,所以我需要手动解码并使用Object而不是Array 。最后,API端代码仍然如此:

$app ->post('/cidadao/cadastrar', function(Request $request, Response $response) use ($app){ 
     //Container do EntityManager 
     $entityManager = $this -> get('em'); 

     $json = $request->getParam('cidadao'); 
     $json = json_decode($json); 


     try{ 
      //Instância da entidade Login 
      $login = new Login(); 
      //recuperando o parâmetro objeto login do json 
      $fk_login_cidadao = $json -> fk_login_cidadao; 
      //setando valores do objeto login 
      $login ->setLogin($fk_login_cidadao -> login); 
      $login ->setEmail($fk_login_cidadao -> email); 
      $login ->setSenha($fk_login_cidadao -> senha); 
      $login ->setStatus_login($fk_login_cidadao -> status_login); 
      $login ->setAsAdministrador($fk_login_cidadao -> administrador); 

      //salvando login 
      $entityManager->persist($login); 
      $entityManager->flush(); 
      //buscando login recém salvo 
      $loginRepository = $entityManager->getRepository('App\Models\Entity\Login'); 
      //pegando login 
      $loginCidadao = $loginRepository->find($login->getId_login()); 
      //Salvar foto 
      $files = $request->getUploadedFiles(); 
      $newimage = $files['foto']; 
      if ($newimage->getError() === UPLOAD_ERR_OK) { 
       $uploadFileName = $newimage->getClientFilename(); 
       $type = $newimage->getClientMediaType(); 
       $name = uniqid('img-' . date('d-m-y') . '-'); 
       $name .= $newimage->getClientFilename(); 
       // $imgs[] = array('url' => '/Photos/' . $name); 
       //local server 
       $newimage->moveTo("/home/citycare//imgs/$name");#/home/citycare/Imgs/User/$name 
       //localdev 
       $photoURL = "/home/citycare//imgs/$name";#/home/citycare/Imgs/User/$name 
      } 
      //Instância da entidade Cidadao 
      $cidadao = new Cidadao(); 
      //setando valores do objeto cidadao 
      $cidadao ->setFk_login_cidadao($loginCidadao); 
      $cidadao->setNome($json -> nome); 
      $cidadao->setSexo($json -> sexo); 
      $cidadao ->setSobrenome($json -> sobrenome); 
      $cidadao ->setEstado($json -> estado); 
      $cidadao ->setCidade($json -> cidade); 
      $cidadao ->setDir_foto_usuario($photoURL); 
      $entityManager->persist($cidadao); 
      $entityManager->flush(); 
      //retornando confirmação do evento completo 
      $return = $response->withStatus(201)->withHeader('Content-type', 'application/json'); 


     } catch (Exception $ex){ 
      //código e mensagem do erro 
      throw new Exception($ex->getMessage(), $ex->getCode()); 
     } 
     return $return; 
}); 

你的请求正文是声音为米部分,除了这个:Content-Transfer-Encoding: binary我不明白为什么retrofit2将其添加到form-data。但是,我不认为这是您遇到的错误。

在拳头,我认为PHP不是正确解析form-data,因为多余的一点。但后来我意识到你正在解析JSON并以Array的形式访问它。你的json字符串是一个对象,将被PHP JSON解码器解释。

所以最后,你应该访问你的数据(json)对象的值如下:$json->fk_login_cidadao而不是像这样:$json['fk_login_cidadao']。这也适用于其他价值和密钥对。

如果您想测试我的理论,只需将参数$request -> getParam('cidadao')的内容记录或写入文件即可。

+0

我做了一些更改,现在表单数据不会与二进制,但现在的服务说:204,没有内容,所以ParsedBody是空的... –

+0

$ request-> getParsedBody()不适用multipart/form - 数据,所以删除它,这是如果其他子句。 – Scriptonomy

+0

我删除了,但现在我不能得到json数据,当尝试getParam()从请求他们返回null ... https://imgur.com/a/szMf6 ::: API方面。 –