Android上的idHTTP无法接受错误406 [英] Error 406 Not Acceptable with idHTTP on Android

查看:127
本文介绍了Android上的idHTTP无法接受错误406的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用idHTTP和PHP脚本在MySQL数据库上发布插入内容.这是要插入数据库的PHP脚本:

I'm trying to post a insert on a MySQL database using idHTTP and a PHP script. This is the PHP script to insert in the database:

    $mysqli = new mysqli($servidor, $usuario, $senha, $banco);

    // Caso algo tenha dado errado, exibe uma mensagem de erro
    if (mysqli_connect_errno()) trigger_error(mysqli_connect_error());

    $iduser         = quoted_printable_decode($_POST['iduser']);
    $nome           = quoted_printable_decode($_POST['nome']);
    $data           = quoted_printable_decode($_POST['data']);
    $hora           = quoted_printable_decode($_POST['hora']);
    $mensagem       = quoted_printable_decode($_POST['mensagem']);
    $latitude       = quoted_printable_decode($_POST['latitude']);
    $longitude      = quoted_printable_decode($_POST['longitude']);
    $imagem         = $_FILES["imagem"]['tmp_name'];
    $tamanho        = $_FILES['imagem']['size'];

    header($_SERVER["SERVER_PROTOCOL"] . " 200 OK"); 
    header('Content-Type: text/plain; charset="utf-8"');

    if ( $imagem != "none" )
    {
        $fp = fopen($imagem, "rb");
        $conteudo = fread($fp, $tamanho);
        $conteudo = addslashes($conteudo);
        fclose($fp);

        $queryInsercao = "INSERT INTO tabpainel (iduser, nome, data, hora, mensagem, latitude, longitude, imagem) VALUES ('$iduser', '$nome', '$data','$hora','$mensagem', '$latitude', '$longitude', '$conteudo')";

        mysqli_query($mysqli,$queryInsercao) or die("Algo deu errado ao inserir o registro. Tente novamente.");

        if (mysqli_affected_rows($mysqli) > 0)
                include 'baixarpainel.php';
            else
                print utf8_encode("Não foi possível inserir o registro");
        }
        else
            print utf8_encode("Não foi possível carregar a imagem.");
  ?>

在Delphi中,我正在使用此代码:

And in Delp i'm using this:

      FormPHP := TIdMultiPartFormDataStream.Create;

      FormPHP.AddFile       ('imagem',    AImagem,    'image/jpeg');
      FormPHP.AddFormField  ('iduser',    AIDUser,    'utf-8');
      FormPHP.AddFormField  ('nome',      ANome,      'utf-8');
      FormPHP.AddFormField  ('data',      AData,      'utf-8');
      FormPHP.AddFormField  ('hora',      AHora,      'utf-8');
      FormPHP.AddFormField  ('mensagem',  AMensagem,  'utf-8');
      FormPHP.AddFormField  ('latitude',  '1');
      FormPHP.AddFormField  ('longitude', '1');

      Response := TStringStream.Create('',TEncoding.UTF8);

      HTTP:= TIdHTTP.Create(self);
 HTTP.Post('http://addressexample.com/cadastro.php',FormPHP,Response);

运行良好,直到不得不更换托管公司.使用Hostinger可以,但是使用Hostgator则不行.使用Hostgator,idHTTP会在类EIdHTTPProtocalException中引发异常,并显示以下消息:"HTTP/1.1 406不可接受" . Hostgator支持已禁用 mod_security ,这可能会导致问题.

It was working fine until a had to change the hosting company. With Hostinger was ok but with Hostgator it doesn't. With Hostgator the idHTTP raise an exception in the class EIdHTTPProtocalException with the message: "HTTP/1.1 406 Not Acceptable". The Hostgator support has already disabled the mod_security, that could cause the problem.

此异常仅在Android上发生.在Windows上使用相同的应用程序,效果很好.

This exception only occurs on Android. Using the same app on Windows, it works fine.

更新:我尝试了另一件事. PHP脚本是这样的:

UPDATE: I've tried another thing. The PHP script is this:

    // Conecta-se ao banco de dados MySQL
    $mysqli = new mysqli($servidor, $usuario, $senha, $banco);

    // Caso algo tenha dado errado, exibe uma mensagem de erro
    if (mysqli_connect_errno()) trigger_error(mysqli_connect_error());

    # Instanciando o XMLWriter
    $xml = new XMLWriter;
    $xml->openMemory();

    # Definindo o encoding do XML
    $xml->startDocument( '1.0', 'UTF-8');

    # Primeiro elemento do XML
    $xml->startElement("DATAPACKET");
    $xml->writeAttribute("version", "2.0");
        $xml->StartElement("METADATA");
            $xml->startElement("FIELDS");
                $xml->startElement("FIELD");
                    $xml->writeAttribute("attrname", "id");
                    $xml->writeAttribute("fieldtype", "I4");
                $xml->endElement();
                $xml->startElement("FIELD");
                    $xml->writeAttribute("attrname", "iduser");
                    $xml->writeAttribute("fieldtype", "String");
                    $xml->writeAttribute("Width", "30");
                $xml->endElement();
                $xml->startElement("FIELD");
                    $xml->writeAttribute("attrname", "nome");
                    $xml->writeAttribute("fieldtype", "String");
                    $xml->writeAttribute("Width", "200");
                $xml->endElement();
                $xml->startElement("FIELD");
                    $xml->writeAttribute("attrname", "data");
                    $xml->writeAttribute("fieldtype", "String");
                    $xml->writeAttribute("Width", "8");
                $xml->endElement();
                $xml->startElement("FIELD");
                    $xml->writeAttribute("attrname", "hora");
                    $xml->writeAttribute("fieldtype", "String");
                    $xml->writeAttribute("Width", "5");
                $xml->endElement();
                $xml->startElement("FIELD");
                    $xml->writeAttribute("attrname", "mensagem");
                    $xml->writeAttribute("fieldtype", "String");
                    $xml->writeAttribute("Width", "3000");
                $xml->endElement();
                $xml->startElement("FIELD");
                    $xml->writeAttribute("attrname", "latitude");
                    $xml->writeAttribute("fieldtype", "r8");
                $xml->endElement();
                $xml->startElement("FIELD");
                    $xml->writeAttribute("attrname", "longitude");
                    $xml->writeAttribute("fieldtype", "r8");
                $xml->endElement();
                $xml->startElement("FIELD");
                    $xml->writeAttribute("attrname", "imagem");
                    $xml->writeAttribute("fieldtype", "bin.hex");
                    $xml->writeAttribute("subtype", "Binary");
                $xml->endElement();
            $xml->endElement(); //FIELDS
        $xml->endElement(); //METADATA

        $xml->StartElement("ROWDATA"); 
        # Query na tabela escolhida
        $rs_table = $mysqli->query("select * from tabpainel ORDER BY id DESC LIMIT 50");
        while($table = $rs_table->fetch_array(MYSQLI_ASSOC))
            {
                # Transformando array em objeto
                $table = (object)$table;
                # Criando elemento tabela
                $xml->StartElement("ROW");
                # Setando os atributos
                    $xml->writeAttribute("id", "$table->id");
                    $xml->writeAttribute("iduser", "$table->iduser");
                    $xml->writeAttribute("nome", "$table->nome");
                    $xml->writeAttribute("data", "$table->data");
                    $xml->writeAttribute("hora", "$table->hora");
                    $xml->writeAttribute("mensagem", "$table->mensagem");
                    $xml->writeAttribute("latitude", "$table->latitude");
                    $xml->writeAttribute("longitude","$table->longitude");
                    $xml->writeAttribute("imagem", base64_encode("$table->imagem"));
                $xml->endElement();
            }
        # Fechando o ROWDATA
        $xml->endElement();
    # Fechando o elemento DATAPACKET
    $xml->endElement();
    # Encerrando a conexao
    //$con->close();
    # Definindo cabecalho de saida
    header("content-type: application/xml; charset=utf-8");
    # Imprimindo a saida do XML
    print $xml->outputMemory(true);
?>

然后我使用http.get来接收xml:

And I used a http.get to receive the xml:

Http.HandleRedirects:= true;
Http.request.useragent := 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; MAAU)';
MS.Text:= Http.get('http://addressexample.com/baixarpainel.php');
 MS.SaveToFile(FarquivoBaixado);

这在Android上也很好用.问题仍然仅在Android上为http.post.

And this worked just fine on Android too. The problem remains only http.post on Android.

推荐答案

TIdHTTP在所有平台上的工作方式都完全相同,因为Indy使用单个跨平台代码库.因此,生成的HTTP请求在所有平台上都应该完全相同.

TIdHTTP works exactly the same way on all platforms, as Indy uses a single cross-platform codebase. So the generated HTTP request should be exactly the same on all platforms.

当HTTP请求包含一个Accept标头,该标头未指定服务器能够在其中呈现响应的任何媒体类型时,将发生HTTP 406错误.每个

An HTTP 406 error happens when the HTTP request includes an Accept header that does not specify any media type that the server is capable of rendering the response in. Per RFC 2616 Section 14.1:

如果不存在接受"标头字段,则假定客户端接受所有媒体类型.如果存在Accept标头字段,并且服务器无法根据组合的Accept字段值发送可接受的响应,则服务器应发送406(不可接受)响应.

If no Accept header field is present, then it is assumed that the client accepts all media types. If an Accept header field is present, and if the server cannot send a response which is acceptable according to the combined Accept field value, then the server SHOULD send a 406 (not acceptable) response.

您的PHP脚本正在发送text/plain响应,因此,如果发送不允许text/plainAccept标头,则可能导致406错误.听起来Hostgator的强制执行力度要比Hostinger更大.

Your PHP script is sending a text/plain response, so if you send an Accept header that does not allow text/plain then that can cause a 406 error. It sounds like Hostgator is enforcing that more than Hostinger does.

默认情况下,TIdHTTP将其Request.Accept属性设置为以下字符串值:

By default, TIdHTTP sets its Request.Accept property to the following string value:

'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'

从技术上讲,这允许通过*/*使用所有媒体类型,但是其优先级低于某些其他媒体类型.但是,如果服务器正确实现了Accept处理,则该默认值仍应足以允许text/plain响应.

Which technically allows all media types via */*, but just with a lower priority than some other media types. But that default should still be enough to allow a text/plain response, if the server implements Accept handling correctly.

您需要联系Hostgator并与他们讨论问题,因为问题出在他们的头上,而不是您的头上.

You need to contact Hostgator and discuss the issue with them, as the problem is on their end, not yours.

话虽如此,由于您知道服务器响应始终为text/plain,因此您可以在调用Post()之前将以下内容添加到代码中:

That being said, since you know the server response is always text/plain, you could just add the following to your code before calling Post():

HTTP.Request.Accept := 'text/plain';
HTTP.Request.AcceptCharset := 'utf-8';

这篇关于Android上的idHTTP无法接受错误406的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆