上载到跳过Web服务器

时间:2019-05-30 22:44:53

标签: indy delphi-xe6

我正在尝试将JSON文件上传到SKIP(getskip.com)Web服务器,并且收到套接字错误10054。由于他们认为每个人都在使用cUrl,因此他们不太擅长提供示例方法,但是我们仍在使用带有Indy的Delphi XE6。

这是他们提供的。

对于使用OK HTTP的Java:

OkHttpClient client = new OkHttpClient();

MediaType mediaType = MediaType.parse("multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
RequestBody body = RequestBody.create(mediaType, "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"path\"; filename=\"<<file_name>>\"\r\nContent-Type: application/vnd.novadigm.ext\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"data\"\r\n\r\n[{\"file_key\": \"path\", \"store_id\"::<<store_id>>}]\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--");
Request request = new Request.Builder()
  .url("https://upload.goskip.com:8080/v2/backoffice/files/pricebook?type=json")
  .post(body)
  .addHeader("content-type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW")
  .addHeader("Authorization", "Bearer <<api_user_token>>")
  .addHeader("Content-Type", "application/x-www-form-urlencoded")
  .addHeader("User-Agent", "PostmanRuntime/7.13.0")
  .addHeader("Accept", "*/*")
  .addHeader("Cache-Control", "no-cache")
  .addHeader("Postman-Token", "de9932d2-bda0-4df6-8a9a-e2d4f74c2048,d59a9861-1a65-471a-8ada-6e025e985dca")
  .addHeader("Host", "upload.goskip.com:8080")
  .addHeader("accept-encoding", "gzip, deflate")
  .addHeader("content-length", "407")
  .addHeader("Connection", "keep-alive")
  .addHeader("cache-control", "no-cache")
  .build();

Response response = client.newCall(request).execute();

使用Unirest的Java:

HttpResponse<String> response = Unirest.post("https://upload.goskip.com:8080/v2/backoffice/files/pricebook?type=json")
  .header("content-type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW")
  .header("Authorization", "Bearer <<api_user_token>>")
  .header("Content-Type", "application/x-www-form-urlencoded")
  .header("User-Agent", "PostmanRuntime/7.13.0")
  .header("Accept", "*/*")
  .header("Cache-Control", "no-cache")
  .header("Postman-Token", "de9932d2-bda0-4df6-8a9a-e2d4f74c2048,d1ea454e-594c-4746-9de7-e813377ff095")
  .header("Host", "upload.goskip.com:8080")
  .header("accept-encoding", "gzip, deflate")
  .header("content-length", "407")
  .header("Connection", "keep-alive")
  .header("cache-control", "no-cache")
  .body("------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"path\"; filename=\"<<file_name>>\"\r\nContent-Type: application/vnd.novadigm.ext\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"data\"\r\n\r\n[{\"file_key\": \"path\", \"store_id\":<<store_id>>}]\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--")
  .asString();

PHP使用HttpRequest:

<?php

$request = new HttpRequest();
$request->setUrl('https://upload.goskip.com:8080/v2/backoffice/files/pricebook');
$request->setMethod(HTTP_METH_POST);

$request->setQueryData(array(
  'type' => 'json'
));

$request->setHeaders(array(
  'cache-control' => 'no-cache',
  'Connection' => 'keep-alive',
  'content-length' => '407',
  'accept-encoding' => 'gzip, deflate',
  'Host' => 'upload.goskip.com:8080',
  'Postman-Token' => 'de9932d2-bda0-4df6-8a9a-e2d4f74c2048,c7acbc0a-6450-43d1-b4ca-bc2a56cebc4e',
  'Cache-Control' => 'no-cache',
  'Accept' => '*/*',
  'User-Agent' => 'PostmanRuntime/7.13.0',
  'Content-Type' => 'application/x-www-form-urlencoded',
  'Authorization' => 'Bearer <<api_user_token>>',
  'content-type' => 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
));

$request->setBody('------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="path"; filename="<<file_name>>"
Content-Type: application/vnd.novadigm.ext


------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="data"

[{"file_key": "path", "store_id"::<<store_id>>}]
------WebKitFormBoundary7MA4YWxkTrZu0gW--');

try {
  $response = $request->send();

  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}

这是我在印地尝试的方法。我将JSON文件粘贴到表单上的备忘录中:

function TFormJsonWrite.HTTPPost: String;
var
  JsonToSend : TStringStream;
  Response: String;
  IdHTTP1: TIdHTTP;
  IdSSLIOHandlerSocketOpenSSL2: TIdSSLIOHandlerSocketOpenSSL;
begin
  IdSSLIOHandlerSocketOpenSSL2 := TIdSSLIOHandlerSocketOpenSSL.Create;
  IdHTTP1 := TIdHTTP.Create;
  IdHTTP1.Request.CharSet := 'utf-8';

  JsonToSend := TStringStream.Create(memolog.text, TEncoding.UTF8);
  IdHTTP1.Request.ContentDisposition := 'form-data; name=[{"file_key":''' + memolog.text + ''', "store_id"::001}]------WebKitFormBoundary7MA4YWxkTrZu0gW--';
  IdHTTP1.Request.UserAgent := 'Mozilla/3.0 (compatible; Indy Library)';
  IdHTTP1.Request.ContentType := 'multipart/form-data';
  IdHTTP1.Request.Accept := '*/*';
  IdHTTP1.Request.AcceptEncoding := 'gzip,deflate';
  IdHTTP1.Request.ContentLength := -1;
  IdHTTP1.Request.CacheControl := 'no-cache';
  IdHTTP1.Request.Connection := 'keep-alive';
  IdHTTP1.Request.BasicAuthentication := false;
  IdHTTP1.Request.Host := 'upload.goskip.com:8080';
  IdHTTP1.Request.CustomHeaders.Clear;
  IdHTTP1.Request.CustomHeaders.Values['Authorization'] := 'Bearer eyJhbGc.......................';
  IdHTTP1.Request.CustomHeaders.Values['Postman-Token'] := 'de9932d2-bda0-4df6-8a9a-e2d4f74c2048,d59a9861-1a65-471a-8ada-6e025e985dca';
  IdHTTP1.ReadTimeout := 50000;
  IdSSLIOHandlerSocketOpenSSL2.SSLOptions.Method := sslvTLSv1_2;
  IdHTTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL2;
  Response := IdHTTP1.Post('https://upload.goskip.com:8080/v2/backoffice/files/pricebook?type=json', JsonToSend);
  HTTPPost := Response;
  JsonToSend.Free;
  IdHTTP1.Free;
end;

卷曲

Kim@KIMNEW MINGW64 ~
$ curl -F "file=@"C:/mydata/Items-114946.json -H "authorization:Bearer eyJ........................." https://upload.goskip.com:8080/v2/backoffice/files/pricebook?type=json&store_id=001
[1] 13296
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
Kim@KIMNEW MINGW64 ~
100  951k  100    53  100  951k     53   968k  0:00:01 --:--:--  0:00:01  967k{"message":"#/data: null value where array expected"}

他们更新了所有端点,这是我得到的最新消息。

curl -X POST   'https://upload.goskip.com:8080/v2/backoffice/files/pricebook?type=json'   -H 'Authorization: Bearer <api_user_token>' -F path=@<path_to_first_file>   -F path1=@<path_to_second_file>   -F 'data=[{"file_key":"path","store_id":<store_id_for_first_file>},{"file_key":"path1","store_id":<store_id_for_second_file>}]'

1 个答案:

答案 0 :(得分:2)

您的Delphi代码都是错误的。

您将错误的Content-Disposition标头设置为错误的值。

您将按原样发布JSON数据,而根本没有将其包装在MIME中。

请勿手动设置TIdHTTP.Request.AcceptEncoding属性。您不是要设置TIdHTTP来启用压缩支持,而是要授予服务器发送压缩响应的权限,TIdHTTP将无法为您解压缩。

使用multipart/form-data发送TIdHTTP请求的正确方法是使用以Post()作为输入的重载TIdMultipartFormDataStream方法,像这样:

function TFormJsonWrite.HTTPPost: String;
var
  JsonToSend : String;
  IdHTTP1: TIdHTTP;
  IdSSLIOHandlerSocketOpenSSL2: TIdSSLIOHandlerSocketOpenSSL;
  PostData: TIdMultipartFormDataStream;
begin
  JsonToSend := '[{"file_key": "path", "store_id": <<store_id>>}]';

  IdHTTP1 := TIdHTTP.Create;
  try
    IdHTTP1.ReadTimeout := 50000;

    IdHTTP1.Request.BasicAuthentication := false;
    IdHTTP1.Request.CustomHeaders.Values['Authorization'] := 'Bearer ...';
    IdHTTP1.Request.CustomHeaders.Values['Postman-Token'] := '...';

    IdSSLIOHandlerSocketOpenSSL2 := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP1);
    IdSSLIOHandlerSocketOpenSSL2.SSLOptions.Method := sslvTLSv1_2;
    IdHTTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL2;

    PostData := TIdMultipartFormDataStream.Create;
    try
      PostData.AddFormField('path', '', '', 'application/vnd.novadigm.ext').FileName := '<<file_name>>';
      PostData.AddFormField('data', JsonToSend, 'utf-8', 'application/json').ContentTransfer := '8bit';

      Result := IdHTTP1.Post('https://upload.goskip.com:8080/v2/backoffice/files/pricebook?type=json', PostData);
    finally
      PostData.Free;
    end;
  finally
    IdHTTP1.Free;
  end;
end;

如果服务器偶然遇到TIdMultipartFormDataStream如何格式化MIME数据的问题(即,如果服务器拒绝了由以下命令生成的MIME Content-Type和/或Content-Transfer-Encoding标头)对于每个MIME字段TIdMultipartFormDataStream,由于它尚未符合HTML5所使用的RFC 7578,因此您可以手动设置MIME数据的格式,使其与SKIP的示例完全匹配,如下所示:

function TFormJsonWrite.HTTPPost: String;
var
  JsonToSend : String;
  IdHTTP1: TIdHTTP;
  IdSSLIOHandlerSocketOpenSSL2: TIdSSLIOHandlerSocketOpenSSL;
  PostData: TStringStream;
begin
  JsonToSend := '[{"file_key": "path", "store_id": <<store_id>>}]';

  IdHTTP1 := TIdHTTP.Create;
  try
    IdHTTP1.ReadTimeout := 50000;

    IdHTTP1.Request.ContentType := 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW';
    IdHTTP1.Request.BasicAuthentication := false;
    IdHTTP1.Request.CustomHeaders.Values['Authorization'] := 'Bearer ...';
    IdHTTP1.Request.CustomHeaders.Values['Postman-Token'] := '...';

    IdSSLIOHandlerSocketOpenSSL2 := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP1);
    IdSSLIOHandlerSocketOpenSSL2.SSLOptions.Method := sslvTLSv1_2;
    IdHTTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL2;

    PostData := TStringStream.Create(
      '------WebKitFormBoundary7MA4YWxkTrZu0gW' + EOL +
      'Content-Disposition: form-data; name="path"; filename="<<file_name>>"' + EOL +
      'Content-Type: application/vnd.novadigm.ext' + EOL +
      EOL +
      EOL +
      '------WebKitFormBoundary7MA4YWxkTrZu0gW' + EOL +
      'Content-Disposition: form-data; name="data"' + EOL +
      EOL +
      JsonToSend + EOL +
      '------WebKitFormBoundary7MA4YWxkTrZu0gW--',
      TEncoding.UTF8
    );
    try
      Result := IdHTTP1.Post('https://upload.goskip.com:8080/v2/backoffice/files/pricebook?type=json', PostData);
    finally
      PostData.Free;
    end;
  finally
    IdHTTP1.Free;
  end;
end;

更新:根据您提供的新curl命令,显示的原始示例与命令不匹配。尝试以下类似的方法:

function TFormJsonWrite.HTTPPost: String;
var
  JsonToSend : String;
  IdHTTP1: TIdHTTP;
  IdSSLIOHandlerSocketOpenSSL2: TIdSSLIOHandlerSocketOpenSSL;
  PostData: TIdMultipartFormDataStream;
begin
  JsonToSend := '[{"file_key": "path", "store_id": <<store_id>>}]';

  IdHTTP1 := TIdHTTP.Create;
  try
    IdHTTP1.ReadTimeout := 50000;

    IdHTTP1.Request.BasicAuthentication := false;
    IdHTTP1.Request.CustomHeaders.Values['Authorization'] := 'Bearer ...';
    IdHTTP1.Request.CustomHeaders.Values['Postman-Token'] := '...';

    IdSSLIOHandlerSocketOpenSSL2 := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP1);
    IdSSLIOHandlerSocketOpenSSL2.SSLOptions.Method := sslvTLSv1_2;
    IdHTTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL2;

    PostData := TIdMultipartFormDataStream.Create;
    try
      PostData.AddFile('path', '<<path_to_file>>').ContentTransfer := 'binary';
      PostData.AddFormField('data', JsonToSend, 'utf-8', 'application/json').ContentTransfer := '8bit';

      Result := IdHTTP1.Post('https://upload.goskip.com:8080/v2/backoffice/files/pricebook?type=json', PostData);
    finally
      PostData.Free;
    end;
  finally
    IdHTTP1.Free;
  end;
end;

或者:

function TFormJsonWrite.HTTPPost: String;
var
  JsonToSend : String;
  IdHTTP1: TIdHTTP;
  IdSSLIOHandlerSocketOpenSSL2: TIdSSLIOHandlerSocketOpenSSL;
  PostData: TMemoryStream;
  FS: TIdReadFileExclusiveStream;
begin
  JsonToSend := '[{"file_key": "path", "store_id": <<store_id>>}]';

  IdHTTP1 := TIdHTTP.Create;
  try
    IdHTTP1.ReadTimeout := 50000;

    IdHTTP1.Request.ContentType := 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW';
    IdHTTP1.Request.BasicAuthentication := false;
    IdHTTP1.Request.CustomHeaders.Values['Authorization'] := 'Bearer ...';
    IdHTTP1.Request.CustomHeaders.Values['Postman-Token'] := '...';

    IdSSLIOHandlerSocketOpenSSL2 := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP1);
    IdSSLIOHandlerSocketOpenSSL2.SSLOptions.Method := sslvTLSv1_2;
    IdHTTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL2;

    PostData := TMemoryStream.Create;
    try
      WriteStringToStream(PostData, '------WebKitFormBoundary7MA4YWxkTrZu0gW' + EOL);
      WriteStringToStream(PostData, 'Content-Disposition: form-data; name="path"; filename="<<file_name>>"' + EOL);
      WriteStringToStream(PostData, 'Content-Type: ' + GetMIMETypeFromFile('<<file_name>>') + EOL);
      WriteStringToStream(PostData, 'Content-Transfer-Encoding: binary' + EOL);
      WriteStringToStream(PostData, EOL);

      FS := TIdReadFileExclusiveStream.Create('<<path_to_file>>', fmOpenRead or fmShareDenyWrite);
      try
        PostData.CopyFrom(FS, 0);
      finally
        FS.Free;
      end;

      WriteStringToStream(PostData, EOL);
      WriteStringToStream(PostData, '------WebKitFormBoundary7MA4YWxkTrZu0gW' + EOL);
      WriteStringToStream(PostData, 'Content-Disposition: form-data; name="data"' + EOL);
      WriteStringToStream(PostData, EOL);
      WriteStringToStream(PostData, JsonToSend + EOL, IndyTextEncoding_UTF8);
      WriteStringToStream(PostData, '------WebKitFormBoundary7MA4YWxkTrZu0gW--');

      PostData.Position := 0;

      Result := IdHTTP1.Post('https://upload.goskip.com:8080/v2/backoffice/files/pricebook?type=json', PostData);
    finally
      PostData.Free;
    end;
  finally
    IdHTTP1.Free;
  end;
end;