[转载红鱼儿]Delphi实现微信开发(3)如何使用multipart/form-data格式上传文件

开始前,先看下要实现的微信接口,上传多媒体文件,这个接口是用Form表单形式上传的文件。对我来说,对http的Form表单一知半解,还好,查到这个资料,如果你也和我一样,必须看看这篇文章。

在xalion窑主的指导下,我使用了indy自带的TIdMultiPartFormDataStre

am类,来提交上传的文件。

如果使用indy的idhttp,则调用这个方法,即可以提交Form.

function Post(AURL: string; ASource: TIdMultiPartFormDataStream): string;

在窑主的建议下,使用了TMS Sparkle组件,对TIdMultiPartFormDataStream进行提交。

先实现下面这个函数,向指定网址提交TIdMultiPartFormDataStream对象:

function PostForm(url: string; aSource: TIdMultiPartFormDataStream): string;

var

  FClient: THttpClient;

  Req: THttpRequest;

  Resp: THttpResponse;

//  buffer: TBytes;

begin

  FClient := THttpClient.Create;

  Resp := nil;

  Req := FClient.CreateRequest;

  try

    Req.Uri := url;

    Req.Method := ‘POST‘;

    Req.Headers.SetValue(‘content-type‘, aSource.RequestContentType);

    Req.SetContent(GetContentAsBytes(aSource));

    Resp := FClient.Send(Req);

    Result := TEncoding.UTF8.GetString(Resp.ContentAsBytes);

  finally

    FreeAndNil(Req);

    FreeAndNil(Resp);

    FreeAndNil(FClient);

  end;

end;

上述方法中,使用了GetContentAsBytes函数,把一个TStream转换为TBytes.这个函数是参考TMS Sparkle的实现改写的。

function GetContentAsBytes(aSource: TStream): TBytes;

const

  BufSize = 8192;

var

  BytesRead: Integer;

  TotalRead: Integer;

begin

  Setlength(Result, 0);

  TotalRead := 0;

  repeat

    Setlength(Result, Length(Result) + BufSize);

    BytesRead := aSource.Read(Result[TotalRead], BufSize);

    TotalRead := TotalRead + BytesRead;

  until BytesRead <> BufSize;

  Setlength(Result, TotalRead);

end;

最后,具体封装上传文件的接口。调用这个接口,以变参的方式,返回微信平台返回的结果。具体的实现过程,建立一个TIdMultiPartFormDataStream对象,叫FormData,再调用FormData.AddFile方法,将上传的文件加入其中。之后,利用上面实现的PostForm提交FormData对象,接下来,对微信平台返回的结果进行处理,并利用变参返回。

procedure UploadMedia(access_token, aFilePath: string; var aType: string;

  var media_id: string; var Created_at: TDatetime; var errcode: Integer;

  var errmsg: string);

var

  url: string;

  FormData: TIdMultiPartFormDataStream;

  r: string;

[转载红鱼儿]Delphi实现微信开发(3)如何使用multipart/form-data格式上传文件

  jo: TjsonObject;

  jv: Tjsonvalue;

begin

  url := Format

    (‘http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=%s‘,

    [access_token, aType]);

  FormData := TIdMultiPartFormDataStream.Create;

  try

    FormData.AddFile(‘media‘, aFilePath);

    r := PostForm(url, FormData);

    jo := TjsonObject.ParseJSONValue(r) as TjsonObject;

    if jo.TryGetValue(‘media_id‘, jv) then

    begin

      aType := jo.GetValue(‘type‘).Value;

      media_id := jo.GetValue(‘media_id‘).Value;

      Created_at := DateUtils.UnixToDateTime(jo.GetValue(‘created_at‘)

        .Value.ToInteger, False);

      errcode := 0;

      errmsg := ‘‘;

    end

    else

    begin

      errcode := jo.GetValue(‘errcode‘).Value.ToInteger;

      errmsg := jo.GetValue(‘errmsg‘).Value;

    end;

  finally

    FreeAndNil(FormData);

  end;

end;

调用代码:

procedure Twm.UploadMedia(id: integer; aFile, aType: string);

var

  errcode: integer;

  errmsg: string;

  Created_at: TDateTime;

  stype, media_id: string;

begin

  if not qUploadMedia.Active then

    qUploadMedia.Open;

  stype := aType;

  WX_Impl.UploadMedia(GetAccessToken(id.ToString), aFile, stype, media_id,

    Created_at, errcode, errmsg);

  if errcode = 0 then

  begin

    //写入本地表.

    qUploadMedia.AppendRecord([id, stype, media_id, Created_at, aFile]);

    webLogger.WriteLog(‘上传成功,media_id=:‘ + media_id + ‘  时间:‘ +

      DateToStr(Created_at) + ‘ Type:‘ + sType)

  end

  else

    webLogger.WriteLog(‘上传失败:‘ + errcode.ToString + ‘:‘ + errmsg);

end;

参考的原文地址在这里。

相关文章