[英]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.