问题
I'm trying to send a JSON to the web service with a file and some text, but the server answers as invalid. I have been looking through this for 3 days and can't get what's wrong, so I ask you for help.
This is the web form to talk to the web service:
<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>
And this is what the php developer sent me:
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"
}
So, based on that, I did this in my code (with some content I found here at stackoverflow:
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);
I always get this answer from the server:
{"idDica":0,"fotoDica":null,"horarioDica":null,"textoDica":null,"recomendado":0}
But the right one should be something like this:
{"idDica":91,"fotoDica":"http://serveraddress.com/tips/91/6nyIZA8MPJ.png","horarioDica":1372960438226,"textoDica":"Hello","recomendado":1}
Can anyone have a clue on what am I doing wrong?
Thanks
EDIT: This is the web service code (out of my knowledge):
@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;
}
回答1:
I'd suggest trying specifying the upload filename, too, e.g.:
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", fieldName, filename] dataUsingEncoding:NSUTF8StringEncoding]];
You also use a Content-Type
of file/jpeg
, but the spec from the developer says it should be image/jpeg
or image/png
. So you might want to use:
[body appendData:[@"Content-Type: image/jpeg\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
If neither of those do it, I notice that your values don't exactly match the HTML example, exactly, and given that we don't know what the validation rules are, I'd suggest you use precisely the same values (e.g. idTags
is 2
in the HTML, but aaaaaa;bbbbbb;cccccc
in your Objective-C). But we have no way of knowing what validation the PHP is performing, so eliminate the possibility that you're just not passing some simple validation rule. Make sure you're confident the problem is the forming of the request, and not the data you're passing in the request.
Hopefully your PHP developer can tell you precisely what validation is taking place.
Looking at your sample server source code, I am not familiar enough with this server code to diagnose it, but a couple of thoughts:
It seems like the references that grab the extension of
fileDetail1
when working withfileDetail2
andfileDetail3
seems like it can't be right (what if they were different types?!?). Given that you're passing only one, that's unlikely to be the source of the problem, but it doesn't seem right.It would suggest, though, that consistent with my earlier observation about supplying a filename, it's important to do so, and probably one with a
jpg
extension. I would encourage you to include a filename (even if it's just"test.jpg"
).This code makes me wonder what happens when your request doesn't pass any
foto2
orfoto3
. Hopefully it handles that gracefully, not throwing any exception, but I can't say.I may be misreading this, but it looks like your
idTags
must be numbers separated by semicolons, notaaaaaa;bbbbbb;cccccc
. See the references toLong
.It looks like the same is true with
idImpressoes
, that it should be numbers separate by semicolons, notbom;alegre
.
It strikes me that point 4 and point 5 are the most immediate candidate issues. I'd make both of those numbers and see if that fixes it.
来源:https://stackoverflow.com/questions/17475985/upload-file-and-text-with-method-post-on-ios