簡體   English   中英

Idhttp Indy使用utf-8文件名上傳到Dropbox

[英]Idhttp Indy upload to Dropbox with utf-8 file name

我正在嘗試使用Indy 10和XE8將文件上傳到Dropbox。 雖然文件名類似於“ file.txt”,它可以正常工作,但是對於“файл.txt”來說,我在DropBox上具有“ ????。txt”。 我閱讀了有關utf-8的參數的信息,但不適用於標頭:-(。

如何上傳文件並保存utf-8文件名?

procedure TSaveFilterForm.TestButtonClick(Sender: TObject);
const
  URL = 'https://content.dropboxapi.com/2/files/upload';
var
  IdHTTP: TIdHTTP;
  Source: TFileStream;
  Res: String;
begin                           
  IdHTTP := TIdHTTP.Create(nil);
  try
    IdHTTP.HandleRedirects := True;
    IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
    IdHTTP.Request.BasicAuthentication := False;
    IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'Bearer ' + AccessToken;
    IdHTTP.Request.ContentType := 'application/octet-stream';
    Source := TFileStream.Create('c:\test.txt', fmOpenRead);

    IdHTTP.Request.CustomHeaders.Values['Dropbox-API-Arg'] :=
      Format('{ "path": "%s", "mode": "overwrite"}',
        ['/файл.txt']); // Dropbox => ????.txt
    try
      Res := IdHTTP.Post(URL, Source);
    finally
      Source.Free;
    end;
  finally
    IdHTTP.Free;
  end;
end;

HTTP標頭不能包含非ASCII字符,甚至不能包含UTF-8。 如果您需要在HTTP標頭中發送非ASCII字符,則必須將它們編碼為ASCII兼容格式。

在這種情況下,由於相關標頭包含JSON,因此您可以使用JSON自己的\\uXXXX語法來編碼非ASCII字符:

任何代碼點都可以表示為十六進制數。 此數字的含義由ISO / IEC 10646確定。如果代碼點位於基本多語言平面(U + 0000至U + FFFF)中,則可以將其表示為六個字符的序列:反向固線,后跟小寫字母u,然后是對代碼點進行編碼的四個十六進制數字。 十六進制數字可以是數字(U + 0030至U + 0039)或十六進制字母A至F(大寫(U + 0041至U + 0046)或小寫)(U + 0061至U + 0066)。 因此,例如,僅包含單個\\字符的字符串可以表示為“ \\ ”。

例如:

procedure TSaveFilterForm.TestButtonClick(Sender: TObject);
const
  URL = 'https://content.dropboxapi.com/2/files/upload';
var
  IdHTTP: TIdHTTP;
  Source: TFileStream;
  Res: String;
begin                           
  IdHTTP := TIdHTTP.Create(nil);
  try
    IdHTTP.HandleRedirects := True;
    IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
    IdHTTP.Request.BasicAuthentication := False;
    IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'Bearer ' + AccessToken;
    IdHTTP.Request.ContentType := 'application/octet-stream';

    IdHTTP.Request.CustomHeaders.Values['Dropbox-API-Arg'] := Format(
      '{ "path": "%s", "mode": "overwrite"}',
      ['/\u0444\u0430\u0439\u043B.txt']
    );

    Source := TFileStream.Create('c:\test.txt', fmOpenRead);
    try
      Res := IdHTTP.Post(URL, Source);
      // alternatively, without using TFileStream manually:
      // Res := IdHTTP.Post(URL, 'C:\test.txt');
    finally
      Source.Free;
    end;
  finally
    IdHTTP.Free;
  end;
end;

我建議您使用JSON庫來創建JSON內容。 例如,您可以在Delphi 2010及更高版本中使用Delphi自己的JSON框架 ,例如:

uses
  ...,
  // use DBXJSON in D2010-XE
  // use Data.DBXJSON in XE2-XE5
  // use System.JSON in XE6+
  ;

procedure TSaveFilterForm.TestButtonClick(Sender: TObject);
const
  URL = 'https://content.dropboxapi.com/2/files/upload';
var
  IdHTTP: TIdHTTP;
  Json: TJSONObject;
  Res: String;
begin                           
  IdHTTP := TIdHTTP.Create(nil);
  try
    IdHTTP.HandleRedirects := True;
    IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
    IdHTTP.Request.BasicAuthentication := False;
    IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'Bearer ' + AccessToken;
    IdHTTP.Request.ContentType := 'application/octet-stream';

    Json := TJSONObject.Create;
    try
      Json.AddPair('path', '/файл.txt');
      Json.AddPair('mode', 'overwrite');
      IdHTTP.Request.CustomHeaders.Values['Dropbox-API-Arg'] := Json.ToJSON;
    finally
      Json.Free;
    end;

    Res := IdHTTP.Post(URL, 'C:\test.txt');
  finally
    IdHTTP.Free;
  end;
end;

如果您需要支持其他Delphi版本,則可以使用許多第三方Delphi JSON庫。

對於標題中帶有參數的這些調用,您需要轉義這些字符。 也就是說,當您使用“ Dropbox-API-Arg”標頭時,需要將其設置為“ HTTP標頭安全”。 這意味着對字符0x7F和所有非ASCII字符使用JSON樣式的“ \\ uXXXX”轉義碼。

一些(但不是全部)語言/庫可以為您完成此任務。 例如,對於JavaScript,您可以自己執行以下操作:

var charsToEncode = /[\u007f-\uffff]/g;

function http_header_safe_json(v) {
 return JSON.stringify(v).replace(charsToEncode,
 function(c) {
 return '\\u' + ('000' + c.charCodeAt(0).toString(16)).slice(-4);
 }
 );
}

然后是這樣的:

'Dropbox-API-Arg': http_header_safe_json({ path: dropboxFilePath })

聽起來您的平台不適合您,因此您需要在代碼中實現它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM