在iOS上使用Method POST上载文件和文本
我试图发送一个JSON到一个文件和一些文本的Web服务,但服务器的答案是无效的。 我已经看了3天,不能得到什么错,所以我请求你的帮助。
这是与Web服务交谈的Web表单:
<html> <head> <title>Nova Dica Form</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <form action="http://serveraddress.com/newtip" method="post" enctype="multipart/form-data"> <input type="hidden" name="textoDica" value="Ola teste dica"> <input type="hidden" name="idUsuario" value="2"> <input type="hidden" name="recomendou" value="true"> <input type="hidden" name="idTags" value="2"> <input type="hidden" name="idMarcas" value="1"> <input type="hidden" name="idLocais" value=""> <input type="hidden" name="idCategorias" value=""> <input type="hidden" name="idImpressoes" value=""> <input name="foto1" type="file"> <input name="foto2" type="file"> <input name="foto3" type="file"> <br> <input type="submit" value="Upload"> </form> </body> </html>
这就是php开发者寄给我的东西:
POST /newtip Host: serveraddress.com Content-Type: multipart/form-data Representation: Content-Disposition: form-data; name="textoDica" texto-dica Content-Disposition: form-data; name="foto1" Content-Type: image/jpeg, image/png Content-Transfer-Encoding: binary foto1 Content-Disposition: form-data; name="foto2" Content-Type: image/jpeg, image/png Content-Transfer-Encoding: binary foto2 Content-Disposition: form-data; name="foto3" Content-Type: image/jpeg, image/png Content-Transfer-Encoding: binary foto3 Content-Disposition: form-data; name="recomendou"; recomendou Content-Disposition: form-data; name="idUsuario"; id-usuario Content-Disposition: form-data; name="idTags"; id-tag Content-Disposition: form-data; name="idMarcas"; id-marca Content-Disposition: form-data; name="idLocais"; id-local Content-Disposition: form-data; name="idCategorias"; id-categoria Content-Disposition: form-data; name="idImpressoes"; id-Impressao Response Content-Type: application/json Representation: { "fotoDica" : "http://s3.amazonaws.com/cooltips/dicas/f23f89as.jpg", "horarioDica" : 1372711615696, "idDica" : 21, "recomendado" : 1, "textoDica" : "TesteDica1" }
所以,基于这一点,我在我的代码(有一些内容,我在这里find了在计算器:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://serveraddress.com/newtip"]]]; [request setHTTPMethod:@"POST"]; // Header NSString *boundary = @"---------------------------14737809831466499882746641449"; NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]; [request addValue:contentType forHTTPHeaderField: @"Content-Type"]; // Body NSMutableData *body = [NSMutableData data]; // Dica/Tip [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Disposition: form-data; name=\"textoDica\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Teste de texto blablabla." dataUsingEncoding:NSUTF8StringEncoding]]; // Usuario [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Disposition: form-data; name=\"idUsuario\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"72" dataUsingEncoding:NSUTF8StringEncoding]]; // Recomendou [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Disposition: form-data; name=\"recomendou\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"true" dataUsingEncoding:NSUTF8StringEncoding]]; // Tags [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Disposition: form-data; name=\"idTags\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"aaaaaa;bbbbbb;cccccc" dataUsingEncoding:NSUTF8StringEncoding]]; // Marca [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Disposition: form-data; name=\"idMarcas\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"3" dataUsingEncoding:NSUTF8StringEncoding]]; // Local [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Disposition: form-data; name=\"idLocais\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"4" dataUsingEncoding:NSUTF8StringEncoding]]; // Categorias [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Disposition: form-data; name=\"idCategorias\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"1" dataUsingEncoding:NSUTF8StringEncoding]]; // Impressões [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Disposition: form-data; name=\"idImpressoes\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"bom;alegre" dataUsingEncoding:NSUTF8StringEncoding]]; // Fotos / Image Files [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Disposition: form-data; name=\"foto1\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Type: file/jpeg\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Transfer-Encoding: binary\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; NSData *imageData = UIImageJPEGRepresentation(_fotoArray[0], 0.40); [body appendData:[NSData dataWithData:imageData]]; // Final Boundary [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; // Set the body [request setHTTPBody:body]; NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding]; NSLog(@"%@", returnString);
我总是从服务器得到这个答案:
{"idDica":0,"fotoDica":null,"horarioDica":null,"textoDica":null,"recomendado":0}
但是正确的应该是这样的:
{"idDica":91,"fotoDica":"http://serveraddress.com/tips/91/6nyIZA8MPJ.png","horarioDica":1372960438226,"textoDica":"Hello","recomendado":1}
任何人都可以知道我做错了什么?
谢谢
编辑:这是networking服务代码(出于我的知识):
@POST @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) public DicaRest uploadFile( @FormDataParam("foto1") InputStream uploadedInputStream1, @FormDataParam("foto1") FormDataContentDisposition fileDetail1, @FormDataParam("foto2") InputStream uploadedInputStream2, @FormDataParam("foto2") FormDataContentDisposition fileDetail2, @FormDataParam("foto3") InputStream uploadedInputStream3, @FormDataParam("foto3") FormDataContentDisposition fileDetail3, @FormDataParam("textoDica") String textoDica, @FormDataParam("idUsuario") long idUsuario, @FormDataParam("recomendou") boolean recomendou, @FormDataParam("idTags") String idTags, @FormDataParam("idMarcas") String idMarcas, @FormDataParam("idLocais") String idLocais, @FormDataParam("idCategorias") String idCategorias, @FormDataParam("idImpressoes") String idImpressoes) { if(idTags == null) idTags = ""; if(idMarcas == null) idMarcas = ""; if(idLocais == null) idLocais = ""; if(idCategorias == null) idCategorias = ""; if(idImpressoes == null) idImpressoes = ""; EntityManager em = EntityFactory.getEntityManager("RestCTPU"); em.getTransaction().begin(); DicaRest dicaRest = new DicaRest(); Upload upload = new Upload(); List<File> pathfoto = new ArrayList<File>(); Dica novaDica = new Dica(); int i = 0; try { novaDica.setTextoDica(textoDica); novaDica.setIdUsuario(new Usuario(idUsuario)); novaDica.setRecomendado(recomendou); novaDica.setDataCadastro(new Date()); novaDica.setEstadoHabilitado(true); novaDica = em.merge(novaDica); //LINUX AMI String pathLocal = "/var/lib/tomcat7/webapps/uploadtemp/"+novaDica.getIdDica() + "/"; //WINDOWS //String pathLocal = "C:/teste/"+"dicas/"+novaDica.getIdDica() + "/"; String pathAlvo = "dicas/"+novaDica.getIdDica() + "/"; (new File(pathLocal)).mkdirs(); if (fileDetail1.getFileName().length() > 0) { pathfoto.add( new File(pathLocal+Utilidades.getRandomPass(10)+fileDetail1.getFileName().substring(fileDetail1.getFileName().lastIndexOf(".")))); saveToFile(uploadedInputStream1, pathfoto.get(i).getAbsolutePath()); i++; } if (fileDetail2.getFileName().length() > 0) { pathfoto.add( new File(pathLocal +Utilidades.getRandomPass(10)+fileDetail1.getFileName().substring(fileDetail1.getFileName().lastIndexOf(".")))); saveToFile(uploadedInputStream2, pathfoto.get(i).getAbsolutePath()); i++; } if (fileDetail3.getFileName().length() > 0) { pathfoto.add( new File(pathLocal+Utilidades.getRandomPass(10)+fileDetail1.getFileName().substring(fileDetail1.getFileName().lastIndexOf(".")))); saveToFile(uploadedInputStream3, pathfoto.get(i).getAbsolutePath()); i++; } List<Tag> tags = new ArrayList<Tag>(); if(idTags.length() > 0) { String[] tgs = idTags.split(";"); for(String tag : tgs) { Tag nTag = new Tag(Long.valueOf(tag)); tags.add(nTag); } } novaDica.setTagList(tags); List<Alvo> alvos = new ArrayList<Alvo>(); if(idMarcas.length() > 0) { String[] marcas = idMarcas.split(";"); for(String marca : marcas) { Alvo nAlvo = new Alvo(Long.valueOf(marca)); alvos.add(nAlvo); } } if(idLocais.length() > 0) { String[] locais = idLocais.split(";"); for(String local : locais) { Alvo nAlvo = new Alvo(Long.valueOf(local)); alvos.add(nAlvo); } } novaDica.setAlvoList(alvos); List<CategoriaImpressao> categoriaImpressaoList = new ArrayList<CategoriaImpressao>(); if(idCategorias.length() > 0) { String[] categorias = idCategorias.split(";"); for(String categoria : categorias) { CategoriaImpressao nCat = new CategoriaImpressao(Long.valueOf(categoria)); categoriaImpressaoList.add(nCat); } } if(idImpressoes.length() > 0) { String[] impressoes = idImpressoes.split(";"); for(String impressao : impressoes) { CategoriaImpressao nImpress = new CategoriaImpressao(Long.valueOf(impressao)); categoriaImpressaoList.add(nImpress); } } novaDica.setCategoriaImpressaoList(categoriaImpressaoList); //String uploadedFileLocation = fileDetail1.getFileName(); // save it List<Foto> fts = new ArrayList<Foto>(); for(String foto : upload.doUpload(pathfoto, pathAlvo)) { Foto ft = new Foto(); ft.setUrlFoto(foto); ft.setIdDica(novaDica); ft.setDataCadastro(new Date()); ft.setEstadoHabilitado(true); fts.add(ft); } novaDica.setFotoList(fts); em.persist(novaDica); em.getTransaction().commit(); try { deleteDir(new File(pathLocal)); } catch (Exception e){} dicaRest.setFotoDica(fts.get(0).getUrlFoto()); dicaRest.setHorarioDica(new Date()); dicaRest.setIdDica(novaDica.getIdDica()); dicaRest.setRecomendado(recomendou); dicaRest.setTextoDica(textoDica); } catch (Exception e) { System.out.println(e); } finally { em.close(); em.getEntityManagerFactory().close(); } return dicaRest; }
我会build议尝试指定上传文件名,例如:
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", fieldName, filename] dataUsingEncoding:NSUTF8StringEncoding]];
你也可以使用Content-Type
的file/jpeg
,但是开发者的spec说它应该是image/jpeg
或image/png
。 所以你可能想要使用:
[body appendData:[@"Content-Type: image/jpeg\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
如果这两者都没有这样做,我注意到你的值并不完全匹配HTML示例,并且由于我们不知道validation规则是什么,我build议你使用完全相同的值(例如idTags
在HTML中是2
,但在Objective-C中是aaaaaa;bbbbbb;cccccc
)。 但是我们无法知道PHP正在执行什么validation,所以消除了只是不通过一些简单的validation规则的可能性。 确保您确信问题在于请求的形成,而不是您在请求中传递的数据。
希望你的PHP开发者能够精确地告诉你正在发生什么validation。
看看你的示例服务器源代码,我不太熟悉这个服务器代码来诊断它,但有一些想法:
-
看起来像引用,抓住
fileDetail1
扩展fileDetail2
和fileDetail3
似乎不能正确(如果他们是不同的types?!?)。 鉴于你只通过一个,这不太可能是问题的根源,但这似乎不正确。 -
但是,这将表明,与我以前提供文件名的观察结果一致,这么做很重要,可能是一个带有
jpg
扩展名的文件。 我鼓励你包含一个文件名(即使它只是"test.jpg"
)。 -
这段代码让我想知道当你的请求没有通过任何
foto2
或foto3
时会发生什么。 希望它能妥善处理,不要抛出任何exception,但我不能说。 -
我可能会误解这个,但看起来你的
idTags
必须用分号分隔,而不是aaaaaa;bbbbbb;cccccc
。 请参阅Long
的参考。 -
idImpressoes
看起来也是这样,它应该用分号分开,而不是bom;alegre
。
这让我觉得,第4点和第5点是最直接的候选问题。 我会把这两个数字,看看是否修复它。