Upload file and text with Method POST on iOS

徘徊边缘 提交于 2019-12-11 09:27:16

问题


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:

  1. It seems like the references that grab the extension of fileDetail1 when working with fileDetail2 and fileDetail3 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.

  2. 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").

  3. This code makes me wonder what happens when your request doesn't pass any foto2 or foto3. Hopefully it handles that gracefully, not throwing any exception, but I can't say.

  4. I may be misreading this, but it looks like your idTags must be numbers separated by semicolons, not aaaaaa;bbbbbb;cccccc. See the references to Long.

  5. It looks like the same is true with idImpressoes, that it should be numbers separate by semicolons, not bom;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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!