在iOS上使用Method POST上传文件和文本

时间:2013-07-04 17:57:07

标签: iphone ios objective-c post form-data

我正在尝试使用文件和一些文本向Web服务发送JSON,但服务器回答为无效。 我已经看了3天了,不能弄错,所以我请求你帮忙。

这是与网络服务对话的网络表单:

<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"
}

所以,基于此,我在我的代码中做了这个(我在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);

我总是从服务器得到这个答案:

{"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}

任何人都可以知道我做错了什么吗?

由于

编辑:这是网络服务代码(据我所知):

@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 个答案:

答案 0 :(得分:0)

我建议尝试指定上传文件名,例如:

[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", fieldName, filename] dataUsingEncoding:NSUTF8StringEncoding]];

您还使用Content-Type file/jpeg,但开发人员的规范称其应为image/jpegimage/png。所以你可能想要使用:

[body appendData:[@"Content-Type: image/jpeg\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

如果这些都没有,我注意到你的值与HTML示例不完全匹配,并且鉴于我们不知道验证规则是什么,我建议你使用完全相同的值(例如,idTags在HTML中为2,但在Objective-C中为aaaaaa;bbbbbb;cccccc。但是我们无法知道PHP正在执行什么验证,因此消除了您不传递一些简单验证规则的可能性。确保您确信问题是请求的形成,而不是您在请求中传递的数据。

希望您的PHP开发人员可以准确地告诉您正在进行的验证。


查看您的示例服务器源代码,我不熟悉此服务器代码来诊断它,但有几点想法:

  1. 在使用fileDetail1fileDetail2时,似乎抓住fileDetail3扩展名的引用似乎不正确(如果它们是不同的类型会怎么样? ?!?)。鉴于你只通过一个,这不太可能成为问题的根源,但这似乎不对。

  2. 但是,这表明,与我之前关于提供文件名的观点一致,这样做很重要,可能还有一个jpg扩展名。我建议您添加一个文件名(即使它只是"test.jpg")。

  3. 此代码让我想知道当您的请求未通过任何foto2foto3时会发生什么。希望它优雅地处理,不会抛出任何异常,但我不能说。

  4. 我可能会误解这一点,但您的idTags看起来必须是以分号分隔的数字,而不是aaaaaa;bbbbbb;cccccc。请参阅Long的参考资料。

  5. idImpressoes看起来也是如此,它应该是以分号分隔的数字,而不是bom;alegre

  6. 令我印象深刻的是,第4点和第5点是最直接的候选问题。我会制作这两个数字并查看是否可以解决这个问题。