导航:
论坛 -> 移动应用开发
斑竹:flyers,iamdream
作者:
2022/12/18 20:50:18
标题:
IDHttpServer中,怎么样才能从收到的流中(WebKitFormBoundary),解出图片呢?
浏览:1384
加入我的收藏
楼主:
我客户端是用HBuildx, 服务端是用IDHttpServer, 我客户端上传一个图片, 服务端如果不做任何处理,直接将流保存为文件, 用记事本打开,发现是以下格式 ------W ebKit FormBo unda ry6a7XEkgemCOp1yuE Con tent-Disp osition: f orm-da ta; name="da ta"; file name="a. bmp" Conte nt-Type: im age /bmp BM6*********图片数据********** ------We bKit FormB ound ary6a7XEkgemCOp1yuE-- (上述加了不少空格,以便能在论坛上发表, 否则论坛不支持) (我自已尝试用以下方法,想把中间的图片数据取出来, aStrList.LoadFromStream(ARequestInfo.PostStream); aStrList.Delete(aStrList.Count-1); //删除最后一行 aStrList.Delete(3); //删除第4行 aStrList.Delete(2); //删除第3行 aStrList.Delete(1); //删除第2行 aStrList.Delete(0); //删除第1行 aStrList.SaveToFile(sFileName); 但这样, 保存出来的文件,是0字节.... 本人对流方面, 基本是小白. 恳请大家指点一下. 非常感谢.
----------------------------------------------
...
作者:
2022/12/18 21:46:08
1楼:
procedure TForm1.IdHTTPServerCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); var FileStream: TFileStream; begin if ARequestInfo.PostStream <> nil then begin ARequestInfo.PostStream.Position := 0; FileStream := TFileStream.Create('1.jpg', fmCreate); FileStream.CopyFrom(ARequestInfo.PostStream, ARequestInfo.PostStream.Size); { Copy 流 } FileStream.Free; end; end; 我用这种方式, 接收到的图片, 会有前缀和后缀 ------W ebKit FormBo unda ry6a7XEkgemCOp1yuE Con tent-Disp osition: f orm-da ta; name="da ta"; file name="a. bmp" Conte nt-Type: im age /bmp BM6*********图片数据********** ------We bKit FormB ound ary6a7XEkgemCOp1yuE-- 如何在流中, 定位真实文件的起始和长度呢?
----------------------------------------------
...
作者:
2022/12/18 22:12:36
2楼:
上述字符串中,我故意加了几个空格, 因为,如果不加的话,盒子发不了
----------------------------------------------
...
作者:
2022/12/19 9:50:12
3楼:
自己直接吧图片文件转换成流然后用你服务端的代码保存成文件,再看看文件是否正常,意思就是不经过idhtttserver,看能不能正常使用,如果可以再拆分代码放到idhttpserver上不就可以了
----------------------------------------------
-
作者:
2022/12/19 10:06:03
4楼:
https://www.cnblogs.com/hjk1124/p/15177240.html ---------- 参考上面地址的方法看看
----------------------------------------------
-
作者:
2022/12/19 10:07:59
5楼:
contentType: 'application/json;charset=UTF-8' 设置
----------------------------------------------
-
作者:
2022/12/19 21:23:21
6楼:
如果你的客户端是标准的浏览器,那么,它发出来的文件上传到 HTTP,就应该符合标准的 HTTP 的协议。 因此,你的 IdHTTPServer 收到的,就应该是标准的 http 的东西,里面的内容以及文件,应该是符合 MIME 规范的。 Indy 有几个控件是用来处理 MIME 的,你可以看看。比如,TIdMessage 这个控件。 如果你用这样的控件,它帮你解析好 HTTP 文件,从里面把文件单独处理了。 当然,如果你要自己处理 HTTP 文本,自己分析字符串,找到文件开始的地方,也行。问题是,你要知道你收到的文件是二进制流,还是 BASE 编码的字符串(或者其它编码)。 如果文件在 HTTP 内容里面是二进制流的方式存在,你用 StringList 是没办法处理的。 如果是编码后的文本,可以用 StringList 处理。你的 StringList 处理的代码有问题: aStrList.LoadFromStream(ARequestInfo.PostStream); 你这里 LoadFromStream 以后,你直接 SaveToFile 为一个文本文件,用文本编辑器打开,看看内容是不是正确的。先保证里面的内容正确,再说后面的处理。
----------------------------------------------
-
作者:
2022/12/19 21:33:07
7楼:
另外,你说保存为文件字节数是 0,也许原因就是你的 StringList.LoadFrom Stream 本身没有成功。在执行这个操作之前,你试试: ARequestInfo.PostStream.Position := 0; aStrList.LoadFromStream(ARequestInfo.PostStream);
----------------------------------------------
-
作者:
2022/12/21 1:49:07
8楼:
an observation: -- maybe be necessary look at "signature" on stream to search a "bitmap signature" 0) read your full Stream 1) try find bytes: [66,77] = ...BM... 2) put your Stream in this position 3) save your Stream in disk! for var i: int64 := 0 to ((AMemoryStream.Size div 2) - 1) do begin AMemoryStream.Read(LBuffer, 2); // if (LBuffer[0]=66) and (LBuffer[1]=77) then // this Stream "CAN BE" a bitmap... ...
此帖子包含附件: 大小: 18.7K
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
2022/12/21 18:36:52
9楼:
这是标准的Post过来的数据格式,我认为解析方法有几种: 1,用indy自带的TIdMessageDecoderMIME来解。 2,用Alcinoe中的demo来解。 3,用delphi中Web相关组件来解。 以上限制在上传的文件在2G内,当然,也可以自己写复杂的代码来存更大的文件。 4,不用POST,用 PUT。 5,用 Delphi-Cross-socket 来做服务器,硬盘够就行。 附件是indy的一个例子
----------------------------------------------
delphi 是兴趣,和工作无关,即使它倒闭。又不靠它 delphi 吃饭,怕甚?
作者:
2022/12/24 19:34:18
10楼:
----------------------------------------------
...
作者:
2022/12/24 19:34:43
11楼:
----------------------------------------------
...
作者:
2022/12/24 19:35:13
12楼:
在大家的指导下, 最后我采用TIdMessageDecoderMIME的方法, 具体写法,我还在整理中, 等整理好, 我会在这个贴子里, 再发出来. 只是目前, 在文件名提取时, 不懂如何转码: 我用记事本打开流文件: filename=QQ鎴浘20221212002717.png 这里的fileName是乱码, 原文件名是: QQ截图20221212002717.png 哪位指点一下,该如何转化: QQ鎴浘20221212002717.png ===> QQ截图20221212002717.png (我自已研究好好久,用UTF8等乱转, 都试不对.)
----------------------------------------------
...
作者:
2022/12/26 14:31:15
13楼:
好,我整理了一下, 采用TIdMessageDecoderMIME (但没有解决文件名乱码问题) I := 0; If ARequestInfo.PostStream <> nil then begin ARequestInfo.PostStream.Position := 0; msgEnd := False; boundary := ExtractHeaderSubItem(ARequestInfo.ContentType, 'boundary',QuoteHTTP); startboundary := '--' + boundary; repeat tmp := ReadLnFromStream(ARequestInfo.PostStream, -1, True); until tmp = startboundary; Decoder := TIdMessageDecoderMIME.Create(nil); try TIdMessageDecoderMIME(Decoder).MIMEBoundary := boundary; tsValues := TStringList.Create; try repeat Decoder.SourceStream := ARequestInfo.PostStream; Decoder.FreeSourceStream := False; Decoder.ReadHeader; Inc(I); case Decoder.PartType of mcptAttachment, mcptText: begin ms := TMemoryStream.Create; try ms.Position := 0; newdecoder := Decoder.ReadBody(ms, msgEnd); tmp := Decoder.Headers.Text; fname := Decoder.Filename; Decoder.Free; Decoder := newdecoder; if Decoder <> nil then TIdMessageDecoderMIME(Decoder).MIMEBoundary := boundary; //sleep(100); 盒子朋友: 原文有这个代码, 但我不知道它有什么用处, 就隐掉了. if fname <> '' then begin ms.SaveToFile(fname); // msgEnd := true; end else begin ms.SaveToFile(IntToStr(I) + '.txt'); end; finally ms.Free; end; end; mcptIgnore: Begin FreeAndNil(Decoder); Decoder := TIdMessageDecoderMIME.Create(nil); TIdMessageDecoderMIME(Decoder).MIMEBoundary := boundary; End; mcptEOF: begin FreeAndNil(Decoder); msgEnd := True end; end; until (Decoder = nil) or (msgEnd); finally tsValues.Free; end; finally FreeAndNil(Decoder); end; end;
----------------------------------------------
...
作者:
2023/1/2 15:51:14
14楼:
乱码不关这里事,只要你这里使用utf8就行,要在程序构建之初就指定 indy 套件使用一个编码,但我没在电脑前,忘了,回去找下。
----------------------------------------------
delphi 是兴趣,和工作无关,即使它倒闭。又不靠它 delphi 吃饭,怕甚?
作者:
2023/1/2 16:07:23
15楼:
就一句代码: IdGlobal.GIdDefaultTextEncoding := encUTF8; 来源于indy作者的回答: https://stackoverflow.com/questions/70171786
----------------------------------------------
delphi 是兴趣,和工作无关,即使它倒闭。又不靠它 delphi 吃饭,怕甚?
作者:
2023/1/2 16:20:37
16楼:
感谢 sail2000 (小帆工作室)的指点!!!! 最后,我总结一下代码: I := 0; If ARequestInfo.PostStream <> nil then begin ARequestInfo.PostStream.Position := 0; msgEnd := False; boundary := ExtractHeaderSubItem(ARequestInfo.ContentType, 'boundary',QuoteHTTP); startboundary := '--' + boundary; repeat tmp := ReadLnFromStream(ARequestInfo.PostStream, -1, True); until tmp = startboundary; IdGlobal.GIdDefaultTextEncoding := encUTF8; //加上sail2000 (小帆工作室),这一句,就行了Decoder.Filename就能正确显示汉字了 Decoder := TIdMessageDecoderMIME.Create(nil); try TIdMessageDecoderMIME(Decoder).MIMEBoundary := boundary; tsValues := TStringList.Create; try repeat Decoder.SourceStream := ARequestInfo.PostStream; Decoder.FreeSourceStream := False; Decoder.ReadHeader; Inc(I); case Decoder.PartType of mcptAttachment, mcptText: begin ms := TMemoryStream.Create; try ms.Position := 0; newdecoder := Decoder.ReadBody(ms, msgEnd); tmp := Decoder.Headers.Text; fname := Decoder.Filename; //********** here Decoder.Free; Decoder := newdecoder; if Decoder <> nil then TIdMessageDecoderMIME(Decoder).MIMEBoundary := boundary; if fname <> '' then begin ms.SaveToFile(fname); end else begin ms.SaveToFile(IntToStr(I) + '.txt'); end; finally ms.Free; end; end; mcptIgnore: Begin FreeAndNil(Decoder); Decoder := TIdMessageDecoderMIME.Create(nil); TIdMessageDecoderMIME(Decoder).MIMEBoundary := boundary; End; mcptEOF: begin FreeAndNil(Decoder); msgEnd := True end; end; until (Decoder = nil) or (msgEnd); finally tsValues.Free; end; finally FreeAndNil(Decoder); end; end;
----------------------------------------------
...