2017-01-19 24 views
0

Я пытаюсь загрузить файл в Dropbox с помощью Indy 10 и XE8. В то время как имя файла, например file.txt, работает нормально, но с файлом «файл.txt» или так, у меня есть «????. Txt» на DropBox. Я читал о параметрах с UTF-8, но это не работает с заголовками :-(.Idhttp Indy upload to Dropbox с именем 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; 

ответ

0

Для этих вызовов с параметры в заголовке, вам нужно избежать этих символов. То есть, когда вы используете заголовок «Dropbox-API-Arg», вам нужно сделать его «HTTP-заголовком безопасным». Это означает использование «\ uXXXX» в стиле JSON, escape-коды для символа 0x7F и все символы, отличные от ASCII.

Некоторые, но не все, языки/библиотеки делают это за вас. Например, для 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 }) 

Похоже, ваша платформа не делает это для вас, так что вы хотите осуществить это в вашем коде.

+0

[У Delphi есть своя библиотека JSON] (http://docwiki.embarcadero.com/RADStudio/en/JSON). –

+0

@Greg спасибо. Я нашел такое решение для delphi - http://drcooper.livejournal.com/4186.html. –

1

HTTP-заголовки не могут содержать символы не ASCII, даже UTF-8. Если вам нужно отправить не-ASCII-символы в HTTP-заголовке, они должны быть закодированы в формате, совместимом с ASCII.

В этом случае, поскольку заголовок в вопросе содержит JSON, вы можете использовать собственный \uXXXX синтаксис JSON для кодирующих не-ASCII символы:

Любой точка кода может быть представлена ​​в виде шестнадцатеричного числа. Значение такого числа определяется ISO/IEC 10646. Если кодовая точка находится на базовой многоязычной плоскости (U + 0000 - U + FFFF), то она может быть представлена ​​в виде шестисимвольной последовательности: обратного солидуса, за которым следует строчная буква u, за которой следуют четыре шестнадцатеричные цифры, которые кодируют кодовую точку. Шестнадцатеричные цифры могут быть цифрами (U + 0030 через U + 0039) или шестнадцатеричными буквами от A до F в верхнем регистре (U + 0041 до U + 0046) или в нижнем регистре (U + 0061 через U + 0066). Так, например, строка, содержащая только один обратный символ солидуса, может быть представлена ​​как «\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 собственного JSON framework в Delphi 2010 и позже, например:

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.

+0

спасибо. С \ uXXXX он отлично работает. Я не пробовал TJSONObject, потому что D2009 не так. –

+0

@OlegAdibekov есть много сторонних библиотек JSON, доступных для Delphi, которые поддерживают 2009 год. –

+0

Я использую LkJSON, @RemyLebeau. Но в этом случае будет слишком много IFDEF. 1. DXE6 + + JSON; 2. D2010 + + DBXJSON; 3. D2009 (utf-8) + LkJSON; 4. Старый (Ansi) Delphi + LkJSON. Слишком сложно. –

 Смежные вопросы

  • Нет связанных вопросов^_^