问题
I have a string, recived by my app from web-browser. String contains PNG image, and encoded to base64.
It isn't my stupid idea, convert image to base64 string )) That doing web-broser. HTML5 canvas object doing that, when need to send image to somewhere.
So, how to decode this string to image?
In Delphi I written my web-server, that recives data.
In PHP this can be solved like that:
function base64_to_jpeg( $base64_string, $output_file ) {
$ifp = fopen( $output_file, "wb" );
fwrite( $ifp, base64_decode( $base64_string) );
fclose( $ifp );
return( $output_file );
}
$image = base64_to_jpeg( $my_base64_string, 'tmp.jpg' );
but in delphi, after decoding:
if (sImg <> EmptyStr) then
begin
Coder := TIdDecoderMIME.Create(nil);
MS := TMemoryStream.Create;
try
Coder.DecodeStream(sImg, MS);
MS.SaveToFile(myDir + '1.png');
finally
FreeAndNil(MS);
FreeAndNil(Coder);
end;
end;
I have a black square of Malevich.
Also I tried functions from EncdDesd module of RTL,
if (sImg <> EmptyStr) then
begin
MS := TMemoryStream.Create;
SS := TStringStream.Create(sImg);
try
DecodeStream(SS, MS);
MS.SaveToFile(myDir + '1.png');
finally
FreeAndNil(MS);
FreeAndNil(SS);
end;
end;
I got the same result.
I wrote web-extension for get some info from user web-browser, and web-server using TidHTTPServer. From JS I capture the web-screenshot, and remove some data from exe, after that, I send this string to the server:
var Img = capture().toDataURL();
var Img = Img.replace('data:image/png;base64,','');
if (FLA.AddNewURL(sN,sD,sU,sI,Img)) {
window.close();
} else {
alert('can not establish connection!');
};
...
AddNewURL: function (aName, aDesc,sURL, aOwnerId,aImg) {
var http = new XMLHttpRequest();
var params = 'Owner=' + aOwnerId + '&Name=' + aName + '&Desc=' + aDesc+ '&URL=' + sURL;
if (aImg) {
params = params +'&Img='+aImg;
};
http.open("POST", "http://" + this.host + ":" + this.port + "/addurl", false);
http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
http.send(params);
return (http.status === 200);
},
My web-server recives this data like that:
if (ARequestInfo.Document = '/addurl') then
begin
Id := ARequestInfo.Params.Values['Owner'];
sName := ARequestInfo.Params.Values['Name'];
sDesc := ARequestInfo.Params.Values['Desc'];
sURL := ARequestInfo.Params.Values['URL'];
sImg := ARequestInfo.Params.Values['Img'];
RootLI := nil;
LinksManager.FindByID(Id, RootLI);
if Assigned(RootLI) then
begin
LI := TLinkItem.Create(nil);
LI.name := sName;
LI.Description := sDesc;
LI.URL := sURL;
if (sImg <> EmptyStr) then
begin
MS := TMemoryStream.Create;
SS := TStringStream.Create(sImg);
try
DecodeStream(SS, MS);
MS.SaveToFile(myDir + '1.png');
finally
FreeAndNil(MS);
FreeAndNil(SS);
end;
end;
RootLI.Add(LI, True);
AResponseInfo.ResponseText := 'OK';
end
else
AResponseInfo.ResponseText := 'FAIL';
end;
After all of that I have image, that contains only black color.
回答1:
I solved my problem by other way. In JS I send data via headers(Ajax.setRequestHeader), and the file I send in the POST stream. After that DecodeStream, from EncdDecd is working correctly, I got the image from string.
Id := ARequestInfo.RawHeaders.Values['OwnerId'];
sName := ARequestInfo.RawHeaders.Values['Name'];
sDesc := ARequestInfo.RawHeaders.Values['Desc'];
sURL := ARequestInfo.RawHeaders.Values['URL'];
...
if (ARequestInfo.PostStream <> nil) then //We have the image!
begin
MS := TMemoryStream.Create;
MS2 := TMemoryStream.Create;
try
MS2.LoadFromStream(ARequestInfo.PostStream);
DecodeStream(MS2, MS);
MS.SaveToFile(myDir + '1.png');
finally
FreeAndNil(MS);
FreeAndNil(MS2);
end;
end;
Also you can try mixed of alternative multipart/form-data encoding. But Indy doesn't have implemented classes for parsing recived data in this format.
来源:https://stackoverflow.com/questions/20024803/decode-file-to-stream-from-base64-encoded-string-how-to-do-that