编程语言
首页 > 编程语言> > php-Android上的idHTTP无法接受错误406

php-Android上的idHTTP无法接受错误406

作者:互联网

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

    $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中,我使用的是:

      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 Not Acceptable”. Hostgator支持已禁用mod_security,这可能会导致问题.

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

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

    // 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:

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.

解决方法:

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

当HTTP请求包含没有指定服务器能够在其中呈现响应的任何媒体类型的Accept标头时,就会发生HTTP 406错误.每RFC 2616 Section 14.1

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脚本正在发送文本/纯文本响应,因此,如果您发送不允许文本/纯文本的Accept标头,则可能导致406错误.听起来,Hostgator的强制执行力度要比Hostinger更大.

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

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

从技术上讲,它允许通过* / *的所有媒体类型,但是其优先级低于某些其他媒体类型.但是,如果服务器正确实现了“接受”处理,则该默认值仍应足以允许文本/纯文本响应.

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

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

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

标签:indy,idhttp,php,android,delphi
来源: https://codeday.me/bug/20191112/2023938.html