1

我正在尝试将带有文件和一些文本的 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"
}

因此,基于此,我在代码中执行了此操作(我在 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; 
}
4

1 回答 1

0

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

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

您还使用 a Content-Typeof file/jpeg,但开发人员的规范说它应该是image/jpegor image/png。所以你可能想使用:

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

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

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


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

  1. 似乎引用在使用fileDetail1时抓住了扩展,fileDetail2并且fileDetail3似乎不可能是正确的(如果它们是不同的类型怎么办?!?)。鉴于您只通过了一个,这不太可能是问题的根源,但它似乎并不正确。

  2. 不过,这表明这与我之前关于提供文件名的观察一致,这样做很重要,而且可能带有jpg扩展名。我鼓励你包含一个文件名(即使它只是"test.jpg")。

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

  4. 我可能误读了这个,但看起来你idTags必须是用分号分隔的数字,而不是aaaaaa;bbbbbb;cccccc. 请参阅对 的引用Long

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

令我震惊的是,第 4 点和第 5 点是最直接的候选人问题。我会制作这两个数字,看看是否可以解决它。

于 2013-07-04T18:38:05.013 回答