2016-11-28 5 views
2

idHTTP 및 PHP 스크립트를 사용하여 MySQL 데이터베이스에 삽입을 게시하려고합니다. 오류 406 Android에서 idHTTP를 사용할 수 없음

$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."); 
    ?> 

그리고 델파이

, 내가 이것을 사용하고 있습니다 : A는 호스팅 업체를 변경했다 때까지 잘 작동했다

 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); 

이 데이터베이스에 삽입하는 PHP 스크립트입니다. Hostinger는 괜찮 았지만 Hostgator는 그렇지 않습니다. Hostgator를 사용하면 idHTTP가 EIdHTTPProtocalException 클래스에서 예외를 발생시킵니다. "HTTP/1.1 406 Not Acceptable". Hostgator 지원은 이미 mod_security을 사용 중지하여 문제를 일으킬 수 있습니다.

이 예외는 Android에서만 발생합니다. Windows에서 동일한 응용 프로그램을 사용하면 정상적으로 작동합니다.

업데이트 : 다른 것을 시도했습니다.

// 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); 
?> 

그리고는 XML받을 http.get을 사용 : PHP 스크립트는 이것이다

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); 

을 그리고이 너무 안드로이드에 잘했습니다. 문제는 안드로이드에만 http.post 남아 있습니다.

+0

주제에서 벗어났습니다. mysqli 대신 PDO를 사용하십시오. 혹시 그것에 대해 들어 본 적이 없다면 google을 사용해보십시오. 코드와 안전성이 향상됩니다. –

+0

Alberto. 나는 그것을 Google 거 야. – wordermorr

답변

3

TIdHTTP은 모든 플랫폼에서 똑같이 작동합니다. Indy는 단일 플랫폼 간 코드베이스를 사용하기 때문입니다. 따라서 생성 된 HTTP 요청은 모든 플랫폼에서 동일해야합니다. .

HTTP 요청은 서버에서 응답을 렌더링 할 수있는 용지 유형을 지정하지 않는 Accept 헤더를 포함 할 때 406 오류가 발생하는 HTTP 당 RFC 2616 Section 14.1 :

더 수락 헤더 필드가없는 경우 현재, 클라이언트가 모든 미디어 유형을 수용한다고 가정한다. Accept 헤더 필드가 존재하고 서버가 결합 된 Accept 필드 값에 따라 수용 가능한 응답을 전송할 수없는 경우 서버는 406 (허용되지 않는) 응답을 보내야합니다 (SHOULD). 당신이 406 오류가 발생할 수있는 다음 text/plain을 허용하지 않는 Accept 헤더를 보내 그래서 만약

귀하의 PHP 스크립트는 text/plain 응답을 전송한다. Hostgator가 Hostinger가하는 것 이상의 것을 시행하고있는 것 같습니다. 기본적으로

TIdHTTP 다음 문자열 값의 Request.Accept 속성을 설정 기술적으로 */*를 통해 모든 미디어 유형을 허용하지만, 단지 다른 미디어 유형보다 우선 순위가 낮은

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

합니다. 그러나 서버가 Accept을 올바르게 처리하면 기본값은 여전히 ​​text/plain 응답을 허용하기에 충분해야합니다.

Hostgator에 연락하여 문제를 논의해야합니다. 문제는 귀하의 문제가 아니라 최종적인 문제입니다.서버 응답이 항상 text/plain 알고 있기 때문에

가 있음을 의미하며, 당신은 단지 Post()를 호출하기 전에 코드에 다음을 추가 할 수

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

Windows에서는 괜찮습니다. 문제는 Android에서만 발생합니다. 동일한 응용 프로그램입니다. accept와 accept charset을 추가했지만 어느 것도 작동하지 않았다. 나는 Hostgator에게 다시 연락을 시도 할 것이지만, 그들은 이미 잘못 될 수있는 것이 무엇인지 모른다고 말했다. – wordermorr

+0

레미, 내 대답을 확인하십시오. – wordermorr

+0

@wordermorr 괜찮은 시스템 관리자는 서버 로그를 추적하고 요청을 추적 할 수 있어야합니다. HostGator가 자신의 서버에 대한 앱의 문제를 해결할 수 없다고 말하면 다른 제공 업체를 찾아야합니다. –

0

을,이 무슨 일이 있었는지입니다 해결하기 위해 노력 오랜 시간 후.

Windows에서 응용 프로그램이 정상적으로 작동하고 HTTP.GET을 사용하여 서버의 문제가 될 수는 없다고 생각했지만 내 요청에 따라 문제가 발생했습니다.

Astr.Add('Response text: ' + Http.Response.ResponseText); 
Astr.Add(#13); 
Astr.Add('Raw Headers Response: ' + HTTP.Response.RawHeaders.Text); 
Astr.Add(#13); 
Astr.Add('Raw Headers Request: ' + HTTP.Request.RawHeaders.Text); 

이 내가 안드로이드에있어 메시지였다 : 그럼, 내가이 코드를 사용하여 Windows 및 안드로이드에 대한 요청 및 응답 모두의 헤더를 열기 시작

응답 텍스트 : HTTP/1.1 (406) 불가

원시 헤더 응답 : 서버 : nginx를/1.10.2
날짜 : ...
의 Content-Type : text/html과;
캐릭터 세트 = ISO-8859-1
콘텐츠 길이 : 226
연결 : 연결 유지

원시 헤더 요청 : 연결 : 연결 유지
콘텐츠 유형 : 다중/폼 데이터; 경계 = ------ (somenumbers)
콘텐츠 길이 : 0 호스트 : myhost의 수락 : text/html과, 응용 프로그램/XHTML + XML, 응용 프로그램/XML, Q = 0.9, /, Q = 0.8 수락 - 인코딩 : 정체성
사용자 에이전트 : ...

그리고 이것은 윈도우

의 메시지

응답 텍스트이었다 : HTTP/1.1 200 OK

원시 헤더 요청 서버 :/1.10.2 날짜의 nginx ... 콘텐츠 형식 : 응용 프로그램/XML 연결 : 가까운 비바리 : 수락 - 인코딩, 사용자 에이전트

원시 헤더 요청 : 연결 : 계속 -alive

콘텐츠 유형 : multipart/form-data; 경계 = -------- (numebrs) 콘텐츠 길이 : 0 호스트 : myhost 수락 : text/html, application/xhtml + xml, application/xml; q = 0.9, /; q = 0.8 사용자 에이전트 : ...

다른 플랫폼의 동일한 앱이 요청시 다른 헤더를 전송하고있었습니다. 안드로이드에서, idHTTP는 Accept-Encoding을 보내고 있었다. 그래서 이것을 추가하려고 시도했습니다 : HTTP.POST 앞에 Http.Request.AcceptEncoding:= '*';이 붙어서 작동했습니다! 예상대로 XML을 받았습니다.

idHTTP가 요청 수락 - 인코딩을 변경 한 이유는 모르겠지만, 나는 또 다른 하나를 지정했고 나는 때문에 MDN 정의의 하나를 선택 :

*

어떤 경기를 헤더에 아직 나열되지 않은 콘텐츠 인코딩 헤더가없는 경우 기본값은 입니다. 모든 알고리즘이 지원된다는 것을 의미하지는 않습니다. 단지 선호가 표현되지 않는다는 것입니다.

+0

이전 버전의 Indy를 사용해야하며 최신 버전으로 업그레이드해야합니다. Indy는 거의 2 년 전에'Request.AcceptEncoding'을 명시 적으로'identity'로 설정하거나 압축 된 응답을 처리하도록'Compressor'를 지정하지 않으면 더 이상'Accept-Encoding : identity'를 보내지 않기 위해 업데이트되었습니다. 'identity'는 기본적으로 더 이상 서버가 그것을 올바르게 처리하지 않기 때문에 더 이상 보내지지 않습니다. 또한, 당신의 안드로이드 애플 리케이션은'아이디 '하지만 귀하의 Windows 애플 리케이션을 전송하는 것은 당신이 각 애플 리케이션에 인디의 다른 버전을 사용하는 것을 의미하지는 않습니다. 동일한 버전 인 경우 동일한 기본 헤더를 보내야합니다. –

+0

저는 Delphi Seattle과 Indy 10.6.2.5298을 사용하고 있습니다. – wordermorr

+0

현재의 Indy 버전은 10.6.2.5377입니다. 기본 '신원 확인'동작은 5321에서 변경되었습니다. 따라서 업데이트가 없으므로 업그레이드해야합니다. –

0

사용자 에이전트 문자열을 변경하여이 문제를 해결할 수있었습니다. 나는 원격 기계 (서버)에 어떤 보안 장치가 설치되어 있다고 생각한다.

이 난 그냥 요청을 설정 ->은 해당 UserAgent에 :

모질라/5.0 (안드로이드 4.4, 모바일, RV : 41.0) 게코/41.0 파이어 폭스/41.0

을하고 지금은 작동한다!

관련 문제