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 的参数,但它不适用于 headers :-(.
如何上传文件并保存 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;
对于header中参数的调用,需要对这些字符进行转义。也就是说,当您使用“Dropbox-API-Arg”header 时,您需要使其成为“HTTP header 安全”。这意味着对字符 0x7F 和所有 non-ASCII 个字符使用 JSON-style “\uXXXX” 转义码。
一些,但不是全部,languages/libraries 为您做这件事。例如,对于 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 })
听起来您的平台并没有为您做这些,因此您需要在代码中实现它。
HTTP headers 不能包含 non-ASCII 个字符,甚至不能包含 UTF-8。如果您需要在 HTTP header 中发送 non-ASCII 个字符,它们必须以 ASCII-compatible 格式编码。
在这种情况下,由于问题中的 header 包含 JSON,您可以使用 JSON 自己的 \uXXXX
语法来编码 non-ASCII 个字符:
Any code point may be represented as a hexadecimal number. The meaning of such a number is determined by ISO/IEC 10646. If the code point is in the Basic Multilingual Plane (U+0000 through U+FFFF), then it may be represented as a six-character sequence: a reverse solidus, followed by the lowercase letter u, followed by four hexadecimal digits that encode the code point. Hexadecimal digits can be digits (U+0030 through U+0039) or the hexadecimal letters A through F in uppercase (U+0041 through U+0046) or lowercase (U+0061 through U+0066). So, for example, a string containing only a single reverse solidus character may be represented as "\u005C
".
例如:
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 framework,例如:
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;
有很多第 3 方 JSON 库可用于 Delphi,如果您需要支持其他 Delphi 版本。
我正在尝试使用 Indy 10 和 XE8 将文件上传到 Dropbox。虽然像 'file.txt' 这样的文件名可以正常工作,但是如果使用 'файл.txt' 左右,我在 DropBox 上有 '????.txt'。我阅读了有关 utf-8 的参数,但它不适用于 headers :-(.
如何上传文件并保存 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;
对于header中参数的调用,需要对这些字符进行转义。也就是说,当您使用“Dropbox-API-Arg”header 时,您需要使其成为“HTTP header 安全”。这意味着对字符 0x7F 和所有 non-ASCII 个字符使用 JSON-style “\uXXXX” 转义码。
一些,但不是全部,languages/libraries 为您做这件事。例如,对于 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 })
听起来您的平台并没有为您做这些,因此您需要在代码中实现它。
HTTP headers 不能包含 non-ASCII 个字符,甚至不能包含 UTF-8。如果您需要在 HTTP header 中发送 non-ASCII 个字符,它们必须以 ASCII-compatible 格式编码。
在这种情况下,由于问题中的 header 包含 JSON,您可以使用 JSON 自己的 \uXXXX
语法来编码 non-ASCII 个字符:
Any code point may be represented as a hexadecimal number. The meaning of such a number is determined by ISO/IEC 10646. If the code point is in the Basic Multilingual Plane (U+0000 through U+FFFF), then it may be represented as a six-character sequence: a reverse solidus, followed by the lowercase letter u, followed by four hexadecimal digits that encode the code point. Hexadecimal digits can be digits (U+0030 through U+0039) or the hexadecimal letters A through F in uppercase (U+0041 through U+0046) or lowercase (U+0061 through U+0066). So, for example, a string containing only a single reverse solidus character may be represented as "
\u005C
".
例如:
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 framework,例如:
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;
有很多第 3 方 JSON 库可用于 Delphi,如果您需要支持其他 Delphi 版本。