2016-11-19 68 views
-1

我遇到了TIdHTTP和TIdMultipartFormDataStream的情況。idHTTP中的字符編碼錯誤

我的代碼是:

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

解釋:我的應用程序發佈這些領域這個PHP腳本和PHP中的數據保存到MySQL數據庫和返回「Sucesso!」的回覆嚮應用程序通知用戶數據已保存。該文本響應以ANSI編碼。我發現,當我不得不將TStringStream編碼改爲TEncoding.ANSI時,當出現錯誤時它可以識別「Não」字。

直到帖子,變量AMensagem沒問題,但是,當PHP收到文本時,它是不正確的。像這樣的文字:「áÁéÉÉ」看起來像這樣「= E1 = C1 = E9 = C9」。這保存在mysql數據庫中。

我不知道這個問題是與idHTTP或TIdMultipartFormDataStream,甚至用PHP代碼。一切工作正常,這只是編碼,我不知道爲什麼它不工作。

回答

1

被髮送到服務器的內容是不被編碼在UTF-8。

您所有的AddFormField()調用都在ACharset參數中指定text/plain媒體類型,而不是AContentType參數。與AddFile()不同,AddFormField()的第三個參數是字符集,第四個參數是媒體類型。

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

通過使無效的字符集,TIdMultipartFormDataStream最終使用印地內置的原始8位編碼代替,其編碼的Unicode字符U+0000 - U+00FF分別作爲字節$00 - $FF,和所有其他字符作爲字節$3F'?')。您發送的文字發生落在第一個範圍內。

TIdFormDataField目前不從TIdMultipartFormDataStreamTIdHTTP繼承字符集(上工作是正在進行中),所以你必須指定它在每個領域的基礎。

在一個側面說明,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()設置默認TIdFormDataField.ContentTransfer屬性quoted-printable。然而,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']); 

如果你不想TIdFormDataField不要使用quoted-printable的UTF-8文本編碼,可以將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編碼的文本。如果你需要的變量是另一種編碼,你必須將它們轉換爲需要,通過使用:

  1. utf8_decode()(其解碼爲ISO-8859-1):

    $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()讓客戶知道正在使用該編碼字符集其中:

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

所做的更改,但問題依然存在。 – wordermorr

+0

@wordermorr您使用的是Delphi和Indy的版本? –

+0

Delphi西雅圖和Indy 10.6.2.5298 – wordermorr