【问题标题】:posting a file as part of a form将文件作为表单的一部分发布
【发布时间】:2015-05-15 08:24:02
【问题描述】:

我正在尝试将文件和其他一些数据发布到我正在使用 Delphi XE8 编写的应用程序中的网站,但它不起作用。当我使用“Microsoft Network Monitor 3.4”监控网络流量时,文件只发送了一部分,没有发送其他数据。我已经尝试过 Indy 10 和新的 TNetHTTPClient 并得到相同的结果,这告诉我我做错了什么。请帮忙。

印地路

procedure TMyClass.SendFile(aUrl: String);
var
  mCookies: TIdCookieManager;
  pHttp: TIdHTTP;
  PostStream: TIdMultiPartFormDataStream;
  ResponseStream: TStringStream;
  fName, mimeStr: String;
begin
  fName := 'Image000.jpg';
  mCookies := TIdCookieManager.Create(nil);
  pHttp := TIdHTTP.Create(nil);
  pHttp.CookieManager := mCookies;
  PostStream:= TIdMultiPartFormDataStream.Create();
  ResponseStream := TStringStream.Create('');
  mimeStr := GetMIMETypeFromFile(fieldValue); // This returns 'image/pjpeg' instead of 'image/jpeg'. I have manually fixed it and it did not change the result
  PostStream.AddFile('sourceFile', fName, mimeStr);
  PostStream.AddFormField('name1', 'value1');
  PostStream.AddFormField('name2', 'value2');
  PostStream.AddFormField('name3', 'value3');
  PostStream.AddFormField('name4', 'value4');
  PostStream.AddFormField('name5', 'value5');
  .
  .
  .
  pHttp.Request.ContentType := PostStream.RequestContentType;
  pHttp.Request.Accept := '*/*';
  pHttp.Request.AcceptLanguage := 'en-us,en';
  pHttp.Request.AcceptEncoding := 'gzip, deflate';
  pHttp.Post(aUrl, PostStream, ResponseStream); // Get a 500 error from server for bad data
  .
  .
  .
  PostStream.Free();
  ResponseStream.Free();
  mCookies.Free();
  pHttp.Free();
end;

顺便说一下,GetMIMETypeFromFile 返回了错误的值,但即使我硬编码了正确的值,也没有什么不同。

新的 XE8 方式

procedure TMyClass.SendFile(aUrl: String);
var
  mCookies: TCookieManager;
  pHttp: TNetHTTPClient;
  fName: String;
  mpFormData: TMultipartFormData;
  respData: IHTTPResponse;
begin
  fName := 'Image000.jpg';
  mCookies := TCookieManager.Create();
  pHttp := TNetHTTPClient.Create(nil);
  pHttp.CookieManager := mCookies;
  mpFormData := TMultipartFormData.Create();
  mpFormData.AddFile('sourceFile', fName);
  mpFormData.AddField('name1', 'value1');
  mpFormData.AddField('name2', 'value2');
  mpFormData.AddField('name3', 'value3');
  mpFormData.AddField('name4', 'value4');
  mpFormData.AddField('name5', 'value5');
  .
  .
  .
  pHttp.ContentType := 'multipart/form-data';
  pHttp.Accept := '*/*';
  pHttp.AcceptLanguage := 'en-us,en';
  pHttp.AcceptEncoding := 'gzip, deflate';
  mpFormData.Stream.Position := 0;
  respData := pHttp.Post(aUrl, mpFormData.Stream); //Same problem, error 500 here
  .
  .
  .
  mpFormData.Free();
  pHttp.Free();
  mCookies.Free();
end;

我知道服务器工作正常,因为另一个应用程序(用英特尔 XDA 编写)工作正常。该图像是有效的,并且我在此之前进行的所有 Get 调用也有效。 我真的需要帮助。 提前谢谢你

【问题讨论】:

    标签: delphi indy10 delphi-xe8


    【解决方案1】:

    当我使用“Microsoft Network Monitor 3.4”监控网络流量时,文件只发送了一部分,没有发送其他数据。

    您确定显示器只是没有在其 UI 中显示部分数据吗?像 Wireshark 这样的数据包嗅探器会更可靠(或将TIdLog... 组件附加到TIdHTTP),因为它会向您显示实际传输的所有内容。发布TIdMultipartFormDataStream 的唯一可能方法是仅发送文件的一部分并完全跳过其他字段,即在传输文件时套接字断开连接。

    mimeStr := GetMIMETypeFromFile(fieldValue); // 这将返回 'image/pjpeg' 而不是 'image/jpeg'。

    在内部,GetMIMETypeFromFile() 构建自己的硬编码 MIME 类型列表,然后使用操作系统信息覆盖该列表。为.jpg 硬编码的默认值是image/jpeg。然后当它查询操作系统时,它看到image/jpegimage/pjpeg(按此顺序)为.jpg 注册,所以image/pjpeg.jpg 看到的最后一个MIME 类型,这就是GetMIMETypeFromFile() 的结束回来了。

    pHttp.Request.ContentType := PostStream.RequestContentType;

    您不需要,Post() 会在内部为您处理。

    pHttp.Request.AcceptEncoding := 'gzip, deflate';

    根本不要这样做。 Post() 在内部为您处理,这取决于 TIdHTTP.Compressor 是否已分配并准备就绪。

    【讨论】:

    • 我创建了一个“TIdZLibCompressorBase”并将其分配给“pHttp.Compressor”,还下载并使用了Wireshark。现在我可以看到所有字段都通过了,但我仍然遇到服务器返回的代码 500 的问题。您提到 image/pjpeg 来自操作系统。你知道我能找到并纠正它吗?谢谢
    • TIdZLibCompressorBase 是一个抽象基类,不能直接使用。您需要改用后代,例如TIdCompressorZLib。至于 500 错误,如果不查看正在发送的实际 HTTP 请求,则无法诊断,但这通常意味着您可能发送了一个参数值,或者省略了一个必需的参数,导致接收脚本失败。脚本希望您提交的实际 HTML 网络表单是什么样的?
    • 你知道我可以找到并更正导致不正确的 mime 类型的设置吗?
    • 在 Windows 上,Indy 从注册表中获取 MIME 信息,特别是从 HKEY_CLASSES_ROOT\<extension>HKEY_CLASSES_ROOT\Mime\Database\Content Type 键。在这种情况下,HKEY_CLASSES_ROOT\.jpgContent Type 值为image/jpeg,但HKEY_CLASSES_ROOT\Mime\Database\Content Type 具有image/jpegimage/pjpeg 子项,它们都映射到.jpg 扩展名。当 Indy 枚举 HKEY_CLASSES_ROOT\Mime\Database\Content Type 时,来自 image/pjpeg 子键的信息会覆盖来自 image/jpeg 子键的信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多