I have a base64 encoded string which my frontend team has provided me with.The string is a video which was encoded using base64. I want to convert that back into a video file using Php.
I am currently just using the following to decode the string but I don't know how to proceed further.
$decoded = base64_decode ($encoded_string);
There seems to be a way to convert images from string using imagecreatefromstring() function, but I could not find a way to convert it into a video.
Thank you
you should know the video file type. you can decode to original format
$fp=file_put_contents('sample.mp4',base64_decode($encoded_string,true));
Video streams tend to be very large so is isn't a good idea to convert them to plain text in the first place. We'd also need to know the exact mechanism (protocol, format...) used to deliver the base64 string. In any case, once there you can do something like this (error checking omitted for brevity):
$chunk_size = 8192; // Bytes (must be multiple of 4)
$input = fopen('php://input', 'rb');
$output = fopen('/tmp/foo.avi', 'wb');
while ($chunk = fread($input, $chunk_size)) {
fwrite($output, base64_decode($chunk));
}
fclose($output);
fclose($input);
Smaller chunks reduce RAM usage and larger chunks improve I/O performance. You'll need to find a balance that works best for you.
Related
We have an XML file exported from ServiceNow which we are trying to import into our custom PHP app.
Each attachment <sys_attachment> are split into chunks <sys_attachment_doc> which is ordered by the <position> element.
<sys_attachment>
<chunk_size_bytes>734003</chunk_size_bytes>
<compressed>true</compressed>
<content_type>application/pdf</content_type>
<encryption_context display_value="" />
<file_name>Filename.pdf</file_name>
</sys_attachment>
<sys_attachment_doc>
<data>[BASE64 ENCODED STRING HERE]</data>
<length>[STRING LENGTH]</length>
<position>0</position>
</sys_attachment_doc>
<sys_attachment_doc>
<data>[BASE64 ENCODED STRING HERE]</data>
<length>[STRING LENGTH]</length>
<position>1</position>
</sys_attachment_doc>
We have tried combining the string and base64_decoding it but to no avail.
<?php
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="servicenow.pdf"');
//echo base64_decode($chunk0.$chunk1);
echo base64_decode($chunk0).base64_decode($chunk1);
?>
We are unable to find any documentation on how to convert these attachments to files outside of ServiceNow (PHP). Is there an extra step that needs to be done before decoding the string and converting to file (PDF)
Edit: I manage to solve it using #Joey answer. I base64_decode the chunks then afterwards combine it. The combined string is actually gzip compressed. We used gzdecode() to generate the PDF.
$attachment = base64_decode($chunk0).base64_decode($chunk1);
echo gzdecode($attachment);
One thing that may be tripping you up is that <compressed> flag. Since that's reading as true, the data is also gzipped, so attachments start from byte[], which then get gzipped, broken into chunks, and base64 encoded (per chunk!).
I don't know how to do this in php specifically, but this strategy should work:
Base64 decode of each chunk will give you a byte[] per chunk.
Combine those chunks in order of position to give you one big byte stream
gunzip that stream into another big byte stream which should be your file.
how safe the following code is, in case everybody could make use of it:
$file = $_FILES["file"]['tmp_name'];
$contents = file_get_contents($file);
$base64 = base64_encode($contents);
<img src="data:image/png;base64,'.$base64.'">
in case this is not safe agains hackers, etc. how should i secure it?
Char set of a base64 encoded string is ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx yz0123456789+/ and an = sign as a last byte filter.
So no matter what the file contents is, you are putting its base64 encoded value and even without escaping, browser will show the given string in the img tag.
You will however need to make sure that the string actually encodes to an image.
And by the way, you are wasting a lot of your server memory for this task by assigning a new variable in every step.
I am developing mobile app which talks with server via PHP Webservice. This is my first time using PHP. I managed to upload data in to database. Now i need to send an image to store it in ftp server. For that i converted image->hex and sent from my app.
Server Side
I got the hex code but not sure how to convert it in to an image and store in in ftp server. I am really struggling here. I googled it but couldn't find exact one.
Any help is much appreciated.
Convert the HEX string to binary:
$binary = pack("H*", $hex);
pack("H*", ...) is equivalent to hex2bin, which is available since PHP 5.4.
Write it to disk:
file_put_contents("file.png", $binary);
Suppose you have received a hex string in a page where you want to convert this hex to real image. Please check this code snippet will help you or not.
<?php
$hexpic=".......................
.....................";
# convert the hex string to binary
$data = pack("H" . strlen($hexpic), $hexpic);
#write the binary string into an image file
file_put_contents("sample.png", $data);
?>
I have a large string of base64 image data (about 200K). When I try to convert that data by outputting the decoded data with the correct header, the script dies, as if there isn't enough memory. I get no error in my Apache logs. The example code I have below works with small images. How can I decode a large image?
<?php
// function to display the image
function display_img($imgcode,$type) {
header('Content-type: image/'.$type);
header('Content-length: '.strlen($imgcode));
echo base64_decode($imgcode);
}
$imgcode = file_get_contents("image.txt");
// show the image directly
display_img($imgcode,'jpg');
?>
Since base64-encoded data is cleanly separated every 4 bytes (i.e. 3 bytes of plaintext are encoded into 4 bytes of base64-encoded text), you could split your b64 string into multiples of 4 bytes, and process them separately:
while (not at end of string) {
take next 4096 bytes // for example - 4096 is 2^12, therefore a multiple of 4
// you could use much larger blocks, depends on your memory limits
base64-decode them
append the decoded result to a file, or a string, or send it to the output
}
If you have a valid base64 string, this will work identically to decoding it all at once.
OK, here is a closer resolution. While this seems to decode the base64 data in smaller chunks, I still don't get an image in the browser. If I echo the data before I place a header, I get output. Again, this works with a small image but not a large one. Thoughts?
<?php
// function to display the image
function display_img($file,$type) {
$src = fopen($file, 'r');
$data = "";
while(!feof($src)) {
$data .= base64_decode(fread($src, 4096));
}
$length = strlen($data);
header('Content-type: image/'.$type);
header('Content-length: '.$length);
echo $data;
}
// show the image directly
display_img('image.txt','jpg');
?>
Content-length must specify the actual (decoded) content length not the length of the base64 encoded data.
Though I'm not sure that fixing it would solve this problem...
Save the base64 string to an image file using imagejpeg() or the correct function for the different formats, and then display the image with a simple <img> tag.
My PHP web application has an API that can recieve reasonably large files (up to 32 MB) which are base64 encoded. The goal is to write these files somewhere on my filesystem. Decoded of course. What would be the least resource intensive way of doing this?
Edit: Recieving the files through an API means that I have a 32MB string in my PHP app, not a 32 MB source file somewhere on disk. I need to get that string decoded an onto the filesystem.
Using PHP's own base64_decode() isn't cutting it because it uses a lot of memory so I keep running into PHP's memory limit (I know, I could raise that limit but I don't feel good about allowing PHP to use 256MB or so per process).
Any other options? Could I do it manually? Or write the file to disk encoded and call some external command? Any thought?
Even though this has an accepted answer, I have a different suggestion.
If you are pulling the data from an API, you should not store the entire payload in a variable. Using curl or other HTTP fetchers you can automatically store your data in a file.
Assuming you are fetching the data through a simple GET url:
$url = 'http://www.example.com/myfile.base64';
$target = 'localfile.data';
$rhandle = fopen($url,'r');
stream_filter_append($rhandle, 'convert.base64-decode');
$whandle = fopen($target,'w');
stream_copy_to_stream($rhandle,$whandle);
fclose($rhandle);
fclose($whandle);
Benefits:
Should be faster (less copying of huge variables)
Very little memory overhead
If you must grab the data from a temporary variable, I can suggest this approach:
$data = 'your base64 data';
$target = 'localfile.data';
$whandle = fopen($target,'w');
stream_filter_append($whandle, 'convert.base64-decode',STREAM_FILTER_WRITE);
fwrite($whandle,$data);
fclose($whandle);
Decode the data in smaller chunks. Four characters of Base64 data equal three bytes of “Base256” data.
So you could group each 1024 characters and decode them to 768 octets of binary data:
$chunkSize = 1024;
$src = fopen('base64.data', 'rb');
$dst = fopen('binary.data', 'wb');
while (!feof($src)) {
fwrite($dst, base64_decode(fread($src, $chunkSize)));
}
fclose($dst);
fclose($src);
It's not a good idea transfer 32Mb string. But I have a solution for my task, that can accept any size files from browser to app server. Algorithm:
Client
Javascript: Read file from INPUT with FileReader and readAsDataURL() to FILE var.
Cut all of data in FILE from start to first "," position Split it with array_chunks by max_upload_size/max_post_size php var.
Send chunk with UID, chunk number and chunks quantity and wait for response, then send another chunk one by one.
Server Side
Write each chunk until the last one. Then do base64 with streams:
$src = fopen($source, 'r');
$trg = fopen($target, 'w');
stream_filter_append($src, 'convert.base64-decode');
stream_copy_to_stream($src, $trg);
fclose($src);
fclose($trg);
... now you have your base64 decoded file in $target local path. Note! You can not read and write the same file, so $source and $target must be different.