2016-11-19 12 views
-1

TIdHTTP 및 TIdMultipartFormDataStream에 상황이 있습니다.idHTTP에서 문자 인코딩 오류가 발생했습니다.

내 코드는 다음과 같습니다

<?php 
    #cadastro.php - Cadastra os dados enviados na tabela online. 
    $mysqli = new mysqli("mysqlhost","username","password","dbname"); 

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

    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) 
      print "Sucesso!"; 
     else 
      print "Não foi possível inserir o registro"; 
    } 
    else 
     print "Não á foi possível carregar a imagem."; 
    ?> 

설명하면서 :

FormPHP := TIdMultiPartFormDataStream.Create; 
    FormPHP.AddFile('imagem',AImagem,'image/jpeg'); 
    FormPHP.AddFormField('iduser',AIDUser,'text/plain'); 
    FormPHP.AddFormField('nome',ANome,'text/plain'); 
    FormPHP.AddFormField('data',AData,'text/plain'); 
    FormPHP.AddFormField('hora',AHora,'text/plain'); 
    FormPHP.AddFormField('mensagem',AMensagem,'text/plain'); 
    FormPHP.AddFormField('latitude','1','text/plain'); 
    FormPHP.AddFormField('longitude','1','text/plain'); 

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

    HTTP:= TIdHTTP.Create(self); 
    HTTP.Request.CustomHeaders.Clear; 
    HTTP.Request.Clear; 
    HTTP.Request.ContentType:= 'multipart/form-data'; //application/x-www-form-urlencoded 
    HTTP.Request.ContentEncoding:= 'MeMIME'; 
    HTTP.Request.CharSet:= 'utf-8'; 
    HTTP.Request.Referer:= 'http://observadordecascavel.blog.br/cadastro.php'; 
    HTTP.Post('http://observadordecascavel.blog.br/cadastro.php',FormPHP,Response); 

이것은 PHP 스크립트 내 응용 프로그램이 PHP 스크립트에 이러한 필드를 게시하고 PHP는 MySQL 데이터베이스에 데이터를 저장하고 "Sucesso!"라는 응답을 반환합니다. 데이터가 저장되었음을 사용자에게 알리기 위해 응용 프로그램에 전달합니다. 이 텍스트 응답은 ANSI로 인코딩됩니다. TStringStream 인 코드를 TEncoding.ANSI로 변경해야 할 때 뭔가 잘못되었을 때 "Não"단어를 인식 할 수 있다는 것을 발견했습니다.

게시물까지, 변수 AMensagem은 괜찮습니다. 그러나 PHP가 텍스트를 수신하면 올바르지 않습니다. 이와 같은 텍스트 : "á ÁéÉ"는 "= E1 = C1 = E9 = C9"와 같이 보입니다. 이것은 mysql 데이터베이스에 저장된다.

문제가 idHTTP, TIdMultipartFormDataStream 또는 PHP 코드와 관련이 있는지 알 수 없습니다. 모든 것이 잘 작동합니다. 인코딩이 아니기 때문에 작동하지 않는 이유가 없습니다.

답변

1

서버로 전송되는 텍스트가 UTF-8로 인코딩되지 않습니다.

AddFormField() 호출은 모두 AContentType 매개 변수 대신 ACharset 매개 변수에 text/plain 미디어 유형을 지정하고 있습니다. AddFile()과 달리 AddFormField()의 세 번째 매개 변수는 charset이며 네 번째 매개 변수는 미디어 유형입니다. 잘못된 문자 세트를 전달하여

function AddFormField(const AFieldName, AFieldValue: string; const ACharset: string = ''; const AContentType: string = ''; const AFileName: string = ''): TIdFormDataField; overload; 

TIdMultipartFormDataStream 각각 바이트 $00 - $FF, 유니 코드 문자 U+0000 - U+00FF 인코딩 대신 인디의 내장 원시 8 비트 인코딩을 사용하여 종료되고, 모든 다른 문자 바이트 $3F ('?') 등. 을 보내는 텍스트는이 첫 번째 범위에 해당합니다.

TIdFormDataField은 현재 문자 집합을 TIdMultipartFormDataStream 또는 TIdHTTP (상속 받고 있음)에서 상속하지 않으므로 필드 당 기준으로 지정해야합니다.

참고로 MeMIME은 유효한 ContentEncoding 값이 아닙니다. 그리고 어쨌든 multipart/form-data 게시물의 값을 ContentEncoding으로 설정해서는 안됩니다. UTF-8 대신 안시의 사용

FormPHP := TIdMultiPartFormDataStream.Create; 

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

Response := TStringStream.Create(''); 

HTTP := TIdHTTP.Create(Self); 
HTTP.Request.Referer := 'http://observadordecascavel.blog.br/cadastro.php'; 
HTTP.Post('http://observadordecascavel.blog.br/cadastro.php', FormPHP, Response); 

어느 쪽이든, 필드 텍스트 인코딩됩니다 또는

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

HTTP := TIdHTTP.Create(Self); 
HTTP.Request.Referer := 'http://observadordecascavel.blog.br/cadastro.php'; 
HTTP.Post('http://observadordecascavel.blog.br/cadastro.php', FormPHP, Response); 

:

이 대신 같은 더 뭔가를보십시오.


업데이트 : 그 말과 함께 지금, AddFormField() 기본적으로 quoted-printableTIdFormDataField.ContentTransfer 속성을 설정합니다.그러나, PHP의 $_POST 기본적으로 quoted-printable를 디코딩하지 않습니다, 당신은 수동으로 quoted_printable_decode()를 호출해야합니다 :

$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']); 

당신이 quoted-printable를 사용하여 UTF-8 텍스트를 인코딩 TIdFormDataField을 원하지 않는 경우에 ContentTransfer 속성을 설정할 수 있습니다 8bit 대신 : 또는

FormPHP.AddFormField('iduser', AIDUser, 'utf-8').ContentTransfer := '8bit'; 
FormPHP.AddFormField('nome', ANome, 'utf-8').ContentTransfer := '8bit'; 
FormPHP.AddFormField('data', AData, 'utf-8').ContentTransfer := '8bit'; 
FormPHP.AddFormField('hora', AHora, 'utf-8').ContentTransfer := '8bit'; 
FormPHP.AddFormField('mensagem', AMensagem, 'utf-8').ContentTransfer := '8bit'; 
FormPHP.AddFormField('latitude', '1'); 
FormPHP.AddFormField('longitude', '1'); 

:

with FormPHP.AddFormField('iduser', AIDUser) do begin 
    Charset := 'utf-8'; 
    ContentTransfer := '8bit'; 
end; 
with FormPHP.AddFormField('nome', ANome) do begin 
    Charset := 'utf-8'; 
    ContentTransfer := '8bit'; 
end; 
with FormPHP.AddFormField('data', AData) do begin 
    Charset := 'utf-8'; 
    ContentTransfer := '8bit'; 
end; 
with FormPHP.AddFormField('hora', AHora) do begin 
    Charset := 'utf-8'; 
    ContentTransfer := '8bit'; 
end; 
with FormPHP.AddFormField('mensagem', AMensagem) do begin 
    Charset := 'utf-8'; 
    ContentTransfer := '8bit'; 
end; 
FormPHP.AddFormField('latitude', '1'); 
FormPHP.AddFormField('longitude', '1'); 

어느 쪽이든, 당신은 다시 원래의 PHP 코드를 사용할 수 있습니다 :

$iduser   = $_POST['iduser']; 
$nome   = $_POST['nome']; 
$data   = $_POST['data']; 
$hora   = $_POST['hora']; 
$mensagem  = $_POST['mensagem']; 
$latitude  = $_POST['latitude']; 
$longitude  = $_POST['longitude']; 

당신이 quoted-printable 사용 여부는 PHP 변수는 UTF-8 인코딩 된 텍스트를 누른 채 종료됩니다. 다른 인코딩 할 변수가 필요한 경우 사용하여, 필요에 따라, 당신은 변환해야 할 것 중 하나

(ISO-8859-1로 디코딩)
  1. utf8_decode() :

    $iduser   = utf8_decode($iduser); 
    $nome   = utf8_decode($nome); 
    $data   = utf8_decode($data); 
    $hora   = utf8_decode($hora); 
    $mensagem  = utf8_decode($mensagem); 
    $latitude  = utf8_decode($latitude); 
    $longitude  = utf8_decode($longitude); 
    
  2. mb_convert_encoding()

    $iduser   = mb_convert_encoding($iduser, 'desired charset', 'utf-8'); 
    $nome   = mb_convert_encoding($nome), 'desired charset', 'utf-8'); 
    $data   = mb_convert_encoding($data, 'desired charset', 'utf-8'); 
    $hora   = mb_convert_encoding($hora, 'desired charset', 'utf-8'); 
    $mensagem  = mb_convert_encoding($mensagem, 'desired charset', 'utf-8'); 
    $latitude  = mb_convert_encoding($latitude, 'desired charset', 'utf-8'); 
    $longitude  = mb_convert_encoding($longitude, 'desired charset', 'utf-8'); 
    
  3. iconv() :

    $iduser   = iconv('utf-8', 'desired charset', $iduser); 
    $nome   = iconv('utf-8', 'desired charset', $nome); 
    $data   = iconv('utf-8', 'desired charset', $data); 
    $hora   = iconv('utf-8', 'desired charset', $hora); 
    $mensagem  = iconv('utf-8', 'desired charset', $mensagem); 
    $latitude  = iconv('utf-8', 'desired charset', $latitude); 
    $longitude  = iconv('utf-8', 'desired charset', $longitude); 
    

마지막으로 클라이언트에 응답을 보내면 비 ASCII 문자가 포함 된 텍스트를 인코딩해야합니다. 만든

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

if ($imagem != "none") 
{ 
    ... 
    if (mysqli_affected_rows($mysqli) > 0) 
     print utf8_encode("Sucesso!"); 
    else 
     print utf8_encode("Não foi possível inserir o registro"); 
} 
else 
    print utf8_encode("Não á foi possível carregar a imagem."); 
+0

변경하지만 문제는 아직 거기 : 당신은 또한 클라이언트가 해당 인코딩에 사용되고있는 캐릭터 세트 알려 header()를 사용한다. – wordermorr

+0

@wordermorr Delphi 및 Indy의 어떤 버전을 사용하고 있습니까? –

+0

델파이 시애틀과 인디 10.6.2.5298 – wordermorr