zoukankan      html  css  js  c++  java
  • delphi中通过http控件上载文件的问题(紧急) 整理的CSDN 帖子

    http控件能不能实现post文件?
    要求效果就像普通的html中通过表单(form中<INPUT TYPE="FILE" NAME="FILE1" SIZE="50">))发送文件一样.

    我试过用post字符串好像没问题。。但是要实现这种方式没头绪

    换一种说法就是用delphi的http控件提交包含文件的表单。。服务器端用普通的文件上载控件
    像接受html页面中的form提交一样来接受上载的文件。

    http://www.matlus.com/scripts/website.dll/Tutorials?DelphiTCPIP&IndyMultiPartFormData&5gz!!!

    把上面的研究一下,hehe.

    对不起,很长时间没回贴也没结贴
    其实很简单:
    就是利用idhttp.post
    post方法有三个参数
    1。调用的脚本
    2。post的stream
    3。接收返回信息的stream
    问题的关键就是构造符合规范的stream格式(要跟从网页的form中post的一模一样)
    具体的格式看看带的MsMultiPartFormData.pas
    其实可以用例子中带的MsMultiPartFormData.pas,它里面已经封装的很好了。

    我的email: linux_chen@263.net 
    如果需要我把我这边的例子发给你

    例子里面带的例子indy版本要求比较新,好像多了一些属性方法
    在新版本的indy里面已经封装了这种应用,有一个unit叫IdMultipartFormData.pas
    装新版本indy时,必须把老的indy文件完全删除干净,不然装起来老报错。

    我在csdn里说的是用MsMultiPartFormData.pas(它实现发送格式化的请求stream)

    你可以直接包含该单元就可以了,这个只用到indy的post方法,应该delphi自带的indy就可以用了

    网上下载的那个例子indy版本较高。我改了一下,在附件里,你现在应该可以用了

    看完这个应该能解决你的问题,我的问题跟你一样。

    附带的例子由于indy版本的问题,有点小问题(其实用文本工具修改一下dfm,去掉新增的属性就可以了)。我干脆把源码给贴出来吧,版权属于原作者

    一.用于实现form流格式的单元(MsMultiPartFormData.pas)
    unit MsMultiPartFormData;

    interface

    uses
      SysUtils, Classes;

    const
      CONTENT_TYPE = 'multipart/form-data; boundary=';
      CRLF = #13#10;
      CONTENT_DISPOSITION = 'Content-Disposition: form-data; name="%s"';
      FILE_NAME_PLACE_HOLDER = '; filename="%s"';
      CONTENT_TYPE_PLACE_HOLDER = 'Content-Type: %s' + crlf + crlf;
      CONTENT_LENGTH = 'Content-Length: %d' + crlf;

    type
      TMsMultiPartFormDataStream = class(TMemoryStream)
      private
        FBoundary: string;
        FRequestContentType: string;
        function GenerateUniqueBoundary: string;
      public
        procedure AddFormField(const FieldName, FieldValue: string);
        procedure AddFile(const FieldName, FileName, ContentType: string; FileData: TStream); overload;
        procedure AddFile(const FieldName, FileName, ContentType: string); overload;
        procedure PrepareStreamForDispatch;
        constructor Create;
        property Boundary: string read FBoundary;
        property RequestContentType: string read FRequestContentType;
      end;

    implementation

    { TMsMultiPartFormDataStream }

    constructor TMsMultiPartFormDataStream.Create;
    begin
      inherited;
      FBoundary := GenerateUniqueBoundary;
      FRequestContentType := CONTENT_TYPE + FBoundary;
    end;

    procedure TMsMultiPartFormDataStream.AddFile(const FieldName, FileName,
      ContentType: string; FileData: TStream);
    var
      sFormFieldInfo: string;
      Buffer: PChar;
      iSize: Int64;
    begin
      iSize := FileData.Size;
      sFormFieldInfo := Format(CRLF + '--' + Boundary + CRLF + CONTENT_DISPOSITION +
        FILE_NAME_PLACE_HOLDER + CRLF + CONTENT_LENGTH +
          CONTENT_TYPE_PLACE_HOLDER, [FieldName, FileName, iSize, ContentType]);

      Write(Pointer(sFormFieldInfo)^, Length(sFormFieldInfo));
      FileData.Position := 0;
      GetMem(Buffer, iSize);
      try
        FileData.Read(Buffer^, iSize);
        Write(Buffer^, iSize);
      finally
        FreeMem(Buffer, iSize);
      end;
    end;

    procedure TMsMultiPartFormDataStream.AddFile(const FieldName, FileName,
      ContentType: string);
    var
      FileStream: TFileStream;
    begin
      FileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
      try
        AddFile(FieldName, FileName, ContentType, FileStream);
      finally
        FileStream.Free;
      end;
    end;

    procedure TMsMultiPartFormDataStream.AddFormField(const FieldName,
      FieldValue: string);
    var
      sFormFieldInfo: string;
    begin
      sFormFieldInfo := Format(CRLF + '--' + Boundary + CRLF + CONTENT_DISPOSITION + CRLF + CRLF +
        FieldValue, [FieldName]);
      Write(Pointer(sFormFieldInfo)^, Length(sFormFieldInfo));
    end;

    function TMsMultiPartFormDataStream.GenerateUniqueBoundary: string;
    begin
      Result := '---------------------------' + FormatDateTime('mmddyyhhnnsszzz', Now);
    end;

    procedure TMsMultiPartFormDataStream.PrepareStreamForDispatch;
    var
      sFormFieldInfo: string;
    begin
      sFormFieldInfo := CRLF + '--' + Boundary + '--' + CRLF;
      Write(Pointer(sFormFieldInfo)^, Length(sFormFieldInfo));
      Position := 0;
    end;
    end.

    二。调用的方法:
      1。先包含MsMultiPartFormData(uses MsMultiPartFormData;)
      2。把如下代码加到需要的地方
    var
      ResponseStream: TMemoryStream;
      MultiPartFormDataStream: TMsMultiPartFormDataStream;
    begin
      MultiPartFormDataStream := TMsMultiPartFormDataStream.Create;
      ResponseStream := TMemoryStream.Create;
      try
        IdHttp1.Request.ContentType := MultiPartFormDataStream.RequestContentType;
    //添加表单的字段 (前一个参数是字段名,后一个参数是字段值)
        MultiPartFormDataStream.AddFormField('PersonName', edtPersonName.Text);
        MultiPartFormDataStream.AddFormField('Description', edtDescription.Text);
    //添加上载的文件(第一个是字段名,第二个是文件名,第三个是文件类型)
        MultiPartFormDataStream.AddFile(edtFile.Name, edtFile.Text, edtMIMEType.Text);
        { You must make sure you call this method *before* sending the stream }
        MultiPartFormDataStream.PrepareStreamForDispatch;
        MultiPartFormDataStream.Position := 0;
    //调用idhttp的post方法,第一个参数是用于处理上载form的asp/php等等脚本,第三个是接收脚本执行完成后的返回内容)
        IdHTTP1.Post("http://xxx.xxx.com/upload.asp", MultiPartFormDataStream, ResponseStream);
      finally
        MultiPartFormDataStream.Free;
        ResponseStream.Free;
      end;
    end;


    从这些代码可以引出很多应用:
    1。asp里调用其它脚本语言如(php,jsp,等等)。把这段代码用组件实现,在asp中调用,就可以  了。
    2。从普通的应用程序调用asp,php等等脚本
    3。传统的html中,必须在浏览器中选择文件,才能上载(号称是为了安全),通过这个就可以实现
    不通过选择文件,实现上载。

  • 相关阅读:
    字符串数组和字符串的转换
    项目总结3
    解决几种中文乱码的问题
    ipms的sql语句
    ipms综合管理系统的总结2
    ipms综合管理系统的总结
    简答题汇总
    log4net根据日志类型写入到不同的文件中
    NUnit单元测试初试
    log4net
  • 原文地址:https://www.cnblogs.com/zhangzhifeng/p/3399123.html
Copyright © 2011-2022 走看看