将文件作为表单的一部分发布

时间:2015-05-15 08:24:02

标签: delphi indy10 delphi-xe8

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

Indy Way

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编写)可以正常工作。图像有效,并且在此之前我所做的所有获取调用也都有效。 我真的需要帮助。 提前谢谢

1 个答案:

答案 0 :(得分:2)

  

当我使用“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是{{1}所见的最后一种MIME类型这就是.jpg最终返回的内容。

  

pHttp.Request.ContentType:= PostStream.RequestContentType;

你不需要那个,Post()在内部为你处理。

  

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

根本不要这样做。 GetMIMETypeFromFile()根据Post()是否已分配并准备就绪,为您内部处理。