尝试从客户端使用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"}
因此,经过多次尝试,在$ 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')
的内容记录或写入文件即可。
我做了一些更改,现在表单数据不会与二进制,但现在的服务说:204,没有内容,所以ParsedBody是空的... –
$ request-> getParsedBody()不适用multipart/form - 数据,所以删除它,这是如果其他子句。 – Scriptonomy
我删除了,但现在我不能得到json数据,当尝试getParam()从请求他们返回null ... https://imgur.com/a/szMf6 ::: API方面。 –
我需要看看你的postCadadao函数和接口代码。将其添加到问题中。谢谢。 – Scriptonomy
上升。功能代码从改造后运行,所以我只是实现与服务的接口。 –
我需要看看您的请求,发送请求到https://requestb.in/14i0kfg1并在此处留言。 – Scriptonomy