Im trying to upload a file image/file type from mobile app and store that image in the backend. Im using Yii2 framework API to do this. And im using postman to check the API. Im running the below in my action.
/*Uploading documents*/
public function actionUploading_doc() {
$uploads = \yii\web\UploadedFile::getInstanceByName('upfile');
print_r($uploads);exit;
if (empty($uploads)){
return "Must upload at least 1 file in upfile form-data POST";
}
foreach ($uploads as $file){
$filename = time() . $image->name;
$path = "uploads/" . $filename;
$file->saveAs($path);
}
}
When i run this as POST method from postman.. and print the value of $uploads im getting empty value. It mean its not coming to controller.
Please help me in solving this.
For me this is what i did without the UploadFile class
/*Uploading documents*/
public function actionUploading() {
$uploads = \yii\web\UploadedFile::getInstanceByName('upfile');
\yii::$app->request->enableCsrfValidation = false;
$filename = $uploads->name;
$path = "http://localhost/projects/YiiRestful/api/web/uploads/".$filename;
$putdata = fopen("php://input", "r");
// make sure that you have /web/upload directory (writeable)
// for this to work
$path = "uploads/".$filename;
$fp = fopen($path, "w");
while ($data = fread($putdata, 1024))
fwrite($fp, $data);
/* Close the streams */
fclose($fp);
fclose($putdata);
}
I would try something like this... (not tested)
public function actionUploadingDoc() { // good practice to use camel case for methods
$uploads = \yii\web\UploadedFile::getInstances('upfile');
if (empty($uploads)){
return false;
// handle error reporting somewhere else
}
$path = 'uploads/'; // set your path
foreach ($uploads as $upload){
$filename = $path . time() .'_'. $upload->name ;
$upload->saveAs($filename);
}
return true;
}
You can use base64 string to uplod. define function inside controller like this
public function base64_to_jpeg($base64_string, $output_file) {
$path="your/real/path/";
// open the output file for writing
$ifp = fopen( $path.$output_file, 'wb' );
// split the string on commas
// $data[ 0 ] == "data:image/png;base64"
// $data[ 1 ] == <actual base64 string>
$data = explode( ',', $base64_string );
if(count($data)>1) {
$dataText=$data[ 1 ];
} else {
$dataText=$base64_string;
}
// we could add validation here with ensuring count( $data ) > 1
fwrite( $ifp, base64_decode( $dataText ) );
// clean up the file resource
fclose( $ifp );
return $output_file;
}
And use inside action as
public function actionUpload(){
$imgName=md5(uniqid()).'.jpg';
$this->base64_to_jpeg($base64_string, $imgName);
}
Related
I need to add manually files into $_FILES, then I use this method :
public function addToFiles($key, $filename): void {
$tempName = tempnam('/tmp', 'php_files');
$originalName = basename(parse_url($filename, PHP_URL_PATH));
$rawData = file_get_contents($filename);
file_put_contents($tempName, $rawData);
$_FILES[$key]['name'][] = $originalName;
$_FILES[$key]['type'][] = mime_content_type($tempName);
$_FILES[$key]['tmp_name'][] = $tempName;
$_FILES[$key]['error'][] = 0;
$_FILES[$key]['size'][] = strlen($rawData);
}
I see temporary file in temporary directory but move_uploaded_file () return false.
What wrong with this code ?
Thank you
I receive a string of base64 and am able to decode it and put it into a file. The problem is, I would like to create a new image file each time to put this base64 into.
Currently I have a basic code which is able to put contents into the file that is pre-existing but the current code does not create a non-existent file.
$data = base64_decode($data);
$path = 'abc';
var_dump(is_dir($path));
if ( ! is_dir($path)) {
if(mkdir($path, 0777)) {
echo "created dir";
}
}
file_put_contents('tmp.png', $data);
Base64 function to decode
function base64ToFile($base64String, $outputFile) {
$file = fopen($outputFile, "wb");
$data = explode(',', $base64String);
fwrite($file, base64_decode($data[1]));
fclose($file);
return $outputFile;
}
Check this the function will return you the unique name after uploading your image in a directory
$imageBase64=$_POST['image_converted_base64'];//get base64 of image from client end
$unique_name =uploadSingleImage($imageBase64);//function call
//function to upload image and get an unique name to store in db
function uploadSingleImage($base64) {
$uniname = uniqid() . date("Y-m-d-H-i-s") . ".png";
$new_image_url = "../../image/" . $uniname;
$base64 = 'data:image/jpeg;base64,' . $base64;
$base64 = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $base64));
file_put_contents($new_image_url, $base64);
return $uniname;
}
I have a api, which will upload the images of the users to server.
It will take the images in base64 format and send that to server. But the problem is for some user it will take long time, and for some user it works well.
I am not getting why this is happening. But the destination directory is a having 700GB of data.
code for uploading :
`
$file will be having base64 format of image
$this->file = $file;
if ($this->id && !empty($this->path) && !is_null($file)) {
$this->storeFilenameForRemove();
}
if ($file instanceof File) {
if (isset($this->path)) {
$this->temp = $this->path;
$this->path = null;
} else {
$this->path = 'initial';
}
} else if (gettype($file) == 'string') {
if (preg_match('/data:(\w+)\/(\w+);base64,/i', $file, $matches)) {
if ($matches) {
$file = preg_replace('/data:(\w+)\/(\w+);base64,/i', '', $file);
$tmpFile = Array();
$tmpFile['data'] = base64_decode( str_replace(' ', '+', $file) );
if ($matches[1] === 'image') {
$tmpFile['name'] = uniqid().'.png';
} else {
$tmpFile['name'] = uniqid().'.'.$matches[2];
}
$tmpFile['handle'] = fopen( $this->getUploadRootDir().'/'.$tmpFile['name'], 'w' );
// inject the raw image data into the new file
fwrite( $tmpFile['handle'], $tmpFile['data'] );
fclose( $tmpFile['handle'] );
$this->path = $tmpFile['name'];
}
}
} else {
$this->file = $file;
}`
I'm not sure if executing a preg_match on a base64 encoded string is a good idea, while I'm not sure that fixes all of your problems regarding speed I'm positive that implementing a different check for base64 encoded strings would improve the speed.
Replace the following:
if (preg_match('/data:(\w+)\/(\w+);base64,/i', $file, $matches)) {
with this
if ( base64_encode(base64_decode($file)) === $file){
I tried to replace single quotes in a large XML file(110MB) with this code but an error occured. I need a code that can handle atleast 3GB XML file.
Error Message:
Fatal error: Allowed memory size of 134217728 bytes exhausted
(tried to allocate 20449728 bytes) in C:\xampp\htdocs\replace.php on
line 10
<?php
replace_file('electronics.xml', "'", "'");
function replace_file($path, $string, $replace)
{
$file = fopen($path, 'a+');
while (feof($file) === false)
{
$str=file_get_contents($path);
$str=str_replace($string, $replace, fgets($file));
}
fclose($file);
}
echo "replace done";
?>
Reading a large file into php is not recommended. Call a command line that is appropriate, like sed
Reference: http://www.grymoire.com/Unix/Sed.html
Simplify:
$str = str_replace( "'","'",file_get_contents('electronics.xml'));
This is just very wrong:
Opening XML
$file = fopen($path, 'a+');
While Loop for no reason, fgets reads to end of file, so loop completes on first iteration.
while (feof($file) === false)
{
reading in entire contents of same file file again, for no purpose
$str=file_get_contents($path);
Reading in entire file, no length specified, so reading to EOF
$str=str_replace($string, $replace, fgets($file));
}
fclose($file);
Nothing accomplished.
////
//PHP 5.3 + Class find and replace string in files
//
//by Bruce Afruz
//
//2013
//
//example usage for single file:
//
//$new = new fileReplacement('./');
//$new->setExt("check.php");
//$new->changeContents("hello", "goodbye");
//
//example usage for multiple files:
//
//$new = new fileReplacement('./test');
//$new->setExt("*.html");
//$new->changeContents("hello", "goodbye");
//
//to change directory:
//
//$new = new fileReplacement('./test');
//$new->setDir("./test2");
//$new->setExt("*.html");
//$new->changeContents("hello", "goodbye");
////
class fileReplacement
{
private $ext , $dir ;
public function getDir() {
return $this->dir;
}
public function setDir($dir) {
$this->dir = $dir;
}
public function getExt() {
return $this->ext;
}
public function setExt($ext) {
$this->ext = $ext;
}
function __construct($dir) {
$this->dir = $dir;
}
public function rglob($pattern = '*', $flags = 0, $path = '') {
chdir($this->getDir());
$paths = glob($path . '*', GLOB_MARK | GLOB_ONLYDIR | GLOB_NOSORT);
$files = glob($path . $pattern, $flags);
foreach ($paths as $path) {
$files = array_merge($files, $this->rglob($pattern, $flags, $path));
}
return $files;
}
public function changeContents($replace , $sentence , $flags = 0, $path = '') {
$all = $this->rglob($this->getExt() , $flags, $path);
foreach ($all as $file) {
$filename = $file;
$handle = fopen($filename, "r");
$contents = fread($handle, filesize($filename));
fclose($handle);
$contents = str_replace($replace , $sentence, $contents);
if (is_writable($filename)) {
if (!$handle = fopen($filename, 'w+')) {
echo "Cannot open file ($filename)
";
exit;
}
// Write $contents to our opened file.
if (fwrite($handle, $contents) === FALSE) {
echo "Cannot write to file ($filename)
";
exit;
}
echo "Success, wrote content to file ($filename)
";
fclose($handle);
} else {
echo "The file $filename is not writable
";
}
}
}}
I send a png image file to controller in base64 via Ajax. I've already test and sure that controller has received id but still can't save it to public folder.
Here is my controller
public function postTest() {
$data = Input::all();
//get the base-64 from data
$base64_str = substr($data->base64_image, strpos($data->base64_image, ",")+1);
//decode base64 string
$image = base64_decode($base64_str);
$png_url = "product-".time().".png";
$path = public_path('img/designs/' . $png_url);
Image::make($image->getRealPath())->save($path);
// I've tried using
// $result = file_put_contents($path, $image);
// too but still not working
$response = array(
'status' => 'success',
);
return Response::json( $response );
}
Intervention Image gets binary data using file_get_content function:
Reference : Image::make
Your controller should be look like this:
public function postTest() {
$data = Input::all();
$png_url = "product-".time().".png";
$path = public_path().'img/designs/' . $png_url;
Image::make(file_get_contents($data->base64_image))->save($path);
$response = array(
'status' => 'success',
);
return Response::json( $response );
}
$data = Input::all();
$png_url = "perfil-".time().".jpg";
$path = public_path() . "/img/designs/" . $png_url;
$img = $data['fileo'];
$img = substr($img, strpos($img, ",")+1);
$data = base64_decode($img);
$success = file_put_contents($path, $data);
print $success ? $png_url : 'Unable to save the file.';
$file = base64_decode($request['image']);
$safeName = str_random(10).'.'.'png';
$success = file_put_contents(public_path().'/uploads/'.$safeName, $file);
print $success;
This is an easy mistake.
You are using public_path incorrectly. It should be:
$path = public_path() . "/img/designs/" . $png_url;
Also, I would avoid your method of sending the image. Look at a proper upload in a form and use Laravel's Input::file method.
My solution is:
public function postTest() {
$data = Input::all();
//get the base-64 from data
$base64_str = substr($data->base64_image, strpos($data->base64_image, ",")+1);
//decode base64 string
$image = base64_decode($base64_str);
Storage::disk('local')->put('imgage.png', $image);
$storagePath = Storage::disk('local')->getDriver()->getAdapter()->getPathPrefix();
echo $storagePath.'imgage.png';
$response = array(
'status' => 'success',
);
return Response::json( $response );
}
what am i doing is using basic way
$file = base64_decode($request['profile_pic']);
$folderName = '/uploads/users/';
$safeName = str_random(10).'.'.'png';
$destinationPath = public_path() . $folderName;
file_put_contents(public_path().'/uploads/users/'.$safeName, $file);
//save new file path into db
$userObj->profile_pic = $safeName;
}
Store or save base64 images in the public folder image and return file path.
$folderPath = public_path() . '/' . 'images/';
$image_parts = explode(";base64,", $image);
$image_type_aux = explode("image/", $image_parts[0]);
$image_type = $image_type_aux[1];
$image_base64 = base64_decode($image_parts[1]);
$uniqid = uniqid();
$file = $folderPath . $uniqid . '.' . $image_type;
file_put_contents($file, $image_base64);
return $file;
Actually, Input::all() returns an array of inputs so you have following:
$data = Input::all();
Now your $data is an array not an object so you are trying to access the image as an object like:
$data->base64_image
So, it's not working. You should try using:
$image = $data['base64_image'];
Since it's (base64_image) accessible from $_POST then Input::file('base64_image') won't work because Input::file('base64_image') checks the $_FILES array and it's not there in your case.
Here is my solution for the file upload from base_64.
public static function uploadBase64File(Request $request, $requestName = 'imageData', $fileName = null, $uploadPath = 'uploads/images/')
{
try {
$requestFileData = $request->$requestName;
// decode the base64 file
$file = base64_decode(preg_replace(
'#^data:([^;]+);base64,#',
'',
$request->input($requestName)
));
if (in_array($file, ["", null, ' '])) {
return null;
}
//handle base64 encoded images here
if ($fileName == null) {
$fileName = Str::random(10);
}
$extension = '.' . explode('/', explode(':', substr($requestFileData, 0, strpos($requestFileData, ';')))[1])[1];
$filePath = $uploadPath . '' . $fileName . '' . $extension;
// dd($extension);
if (!File::exists(public_path($uploadPath))) {
File::makeDirectory(public_path($uploadPath), 0777, true);
}
// dd($filePath);
$ifImageUploadSuccessful = File::put(public_path($filePath), $file);
if (!$ifImageUploadSuccessful) {
return null;
}
return '/' . $filePath;
// throw new Exception("Unable To upload Image");
} catch (Exception $e) {
// dd($e);
throw new Exception($e->getMessage());
}
}
I'v done it!!
I replaced
$data->base64_image to $_POST['base64_image'] and then use
$result = file_put_contents($path, $image);
instead of Image::make($image->getRealPath())->save($path);
But this doesn't look like a laravel ways. I you have another way that look more elegant please tell me!