File download in headless chrome using Laravel/Dusk - laravel

I'm trying to automate a file download in headless chrome using Laravel/Dusk.In GUI mode,the file downloads just fine in my download folder.But in headless mode,the download does not take place at all.Is there any way to solve this issue?

For those who come across this, I found a simple solution with the current version of Laravel at the time of writing this.
I suggest first creating a directory in your storage path called temp (probably want to gitignore this too), and then navigate to the DuskTestCase.php file setup with the Dusk installation.
Under the driver method, add the following under the section that initializes the ChromeOptions variable.
$options->setExperimentalOption('prefs', [
'download.default_directory' => storage_path('temp')
]);
The driver function should now look like this:
$options = (new ChromeOptions())->addArguments([
'--disable-gpu',
'--headless',
'--window-size=1920,1080'
]);
$options->setExperimentalOption('prefs', [
'download.default_directory' => storage_path('temp')
]);
return RemoteWebDriver::create(
'http://localhost:9515',
DesiredCapabilities::chrome()->setCapability(
ChromeOptions::CAPABILITY,
$options
)
);
As a side note, this worked for me with a PDF file created via JS, so I can't definitively say how this works with a file downloaded from the back-end.

public function testDownload($account){
$this->browse(function (Browser $browser) {
$download_path = storage_path('your/download/path');
$url = $browser->driver->getCommandExecutor()->getAddressOfRemoteServer();
$uri = '/session/' . $browser->driver->getSessionID() . '/chromium/send_command';
$body = [
'cmd' => 'Page.setDownloadBehavior',
'params' => ['behavior' => 'allow', 'downloadPath' => $download_path]
];
(new \GuzzleHttp\Client())->post($url . $uri, ['body' => json_encode($body)]);
// Start your test
$browser->visit("http://example.com/export")
//your asserts here
}

It's not necessary to trigger a separate Guzzle POST, I used a CustomWebDriverCommand instead:
$command = new \Facebook\WebDriver\Remote\CustomWebDriverCommand(
$driver->getSessionID(),
"/session/:sessionId/chromium/send_command",
"POST",
[
"cmd" => "Page.setDownloadBehavior",
"params" => ["behavior" => "allow", "downloadPath" => '/your/download/path']
]
);
$driver->getCommandExecutor()->execute($command);

Related

How to edit picture on Coudinary with Laravel

Any Idea how to edit pictures on Cloudinary using Laravel API? I did a lot of searches, but I didn't find any references. The add worked successfully, but I didn't find a solution for the edit.
Add code
$user->user_image = Cloudinary::upload(
$request->file('user_image')->getRealPath(),
[
'folder' => 'Testing'
]
)->getSecurePath();
Attempt at updating picture
public function updatePicture(Request $request, $user_id)
{
$data = $request->validate([
'user_image' => '',
]);
$data = Cloudinary::upload(
$request->file('user_image')->getRealPath(),
[
'folder' => 'Testing'
]
)->getSecurePath();
User::where("user_id", $user_id)->update($data);
return response()->json([
'message' => 'Successfully updated Picture!',
'success' => true,
], 200);
}
For deleting, you can use the destroy() method of the API, for example:
$result = Cloudinary::destroy(
$public_id, //Public ID of the file from Cloudianry to delete - returned from the Upload API response
[
'...' => '...' //any optional parameters
]
)
For a list of all optional parameters and possible values please see:
https://cloudinary.com/documentation/image_upload_api_reference#destroy_method
In terms of updating, I am assuming you are referring to Cloudinary's update details of a single resource method of the Admin API. If so, you can access it like so:
$admin_api = Cloudinary::admin();
$result = $admin_api->update($public_id, $options = []);
Alternatively, if you're referring to the explicit method of the Upload API then you could access it like so:
$result = Cloudinary::explicit($public_id, $options = []);

Guzzle 7 + Guzzle-cache-middleware

I'm using Guzzle 7 to grab content from an external API with basic authentication. It works fine. Now I'd like to integrate cache management. So i've tried to use this plugin: [Guzzle-cache-middleware][1] and I can't make it working correctly. I can get API response and my desired content but the cache directory is not populated.
I've searched all around the web but I can't figure this out. Could you please tell me how to solve this? Here is my code:
$userName = "xxxxxxx";
$password = "yyyyyyyyyyy";
require_once './vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use Kevinrob\GuzzleCache\CacheMiddleware;
use Kevinrob\GuzzleCache\Strategy\PublicCacheStrategy;
$stack = HandlerStack::create();
$cache = new CacheMiddleware();
$stack->push($cache, '/home/xxxx/xxxxx/guzzle2/cache');
$client = new Client([
'handler' => $stack,
'base_uri' => 'https://api.xxxxx.com/xxx/',
"timeout" => 30.0,
]);
$json = $client->get('zzzzzz.json', [
'auth' => [
$userName,
$password
]
]);
var_dump($json->getHeaderLine(CacheMiddleware::HEADER_CACHE_INFO));
Output:
string(4) "MISS"
So API result is different from cache. But headers params (ETag and Last-Modified) are still unchanged and my cache folder is still blank.
Thank you for your help!

How i can upload image to public folder in shared hosting laravel 5

I moved my website from localhost to shared hosting all it's good, but i need when i upload file stored directly to public_html: something like this
public_html/storage/
I tried use somenthing like :
symlink('/home/abdoweb/bmcelarave/storage/app/public', '/bmce/public_html/storage')
the problem still exists.
my Controller :
public function addcategory(Request $request){
$title = $request->input('category_name');
$image = $request->file('category-image');
$name = $image->getClientOriginalName();
$image->move(storage_path().'/app/public/category',$name);
$data[] = $name;
$query= DB::table('category')->insert(
[
'title' => $title,
'image' => $name,
"created_at" => Carbon::now()
]);
if($query){
return redirect('categories');
}
}
My folder :
home/abdoweb/{bmcelaravel} <= my public folder
Core laravel :
home/{bmce} <= core laravel
Thank you.
You can a use storage driver :
Inside config/filesystems.php :
'disks' => [
'public' => [
'driver' => 'local',
'root' => public_path() . '/uploads',
'url' => env('APP_URL').'/public',
'visibility' => 'public',
]
]
//Now you can move the file to storage like :
Storage::disk('public')->putFile('category', $request->file('category-image'));
First of all the recommended location for that stuff is to stay on the public path not creating a new one, unless there is an actual reason for that. Did you actually check that the symlink was created?
Laravel has an own command the create a symlink from storage/app/public to public/storage (the storage folder will be generated afterwards):
php artisan storage:link
But if you want to create defaults symlinks you should create one for yourself, like you already did.
This is the symlink pattern:
ln -s target source (fill in your target and source path)
So if you actually get the correct file from your request, this code should work:
Storage::putFile($name, $request->file('category-image'));
For more and detailed infos look into the filesystem documentation

How to do an actual file upload with phpunit and Laravel that's not fake

Phpunit, Laravel 5.5
How do I emulate, not fake, an actual file upload with phpunit and Laravel. My latest stab at it is like this. From the unit test:
$handle = fopen($path,'r');
$content = fread($handle,2048);
fclose($handle);
$fdata = [
'delimiter' => '3',
'id' => 1,
'allow_shared_roles' => 'on',
'file'=>$name
];
$this->call('POST','/event/add-wizard/2',$fdata,[],[],[
'Content-Length'=>strlen($content),
'Content-Type'=>'multipart/form-data;boundary='.$content,
'Content-Disposition'=>'form-data;name="file";filename="'.$name.'"'
],$content);
Then on the server side, this is where I get hung up.
if ($request->hasFile('file')) {
$input['extension'] = strtolower($request->file('file')->getClientOriginalExtension());
}
$validator = \Validator::make($input, ['file' => 'required', 'extension' => 'in:csv', 'delimiter' => 'required'], ['extension.in' => 'The file must be a .csv file.']);
if ($validator->fails()) {
return \Redirect::back()->withInput()->withErrors($validator);
}
if (!file_exists(storage_path('temp-files'))) {
\File::makeDirectory(storage_path('temp-files'));
}
$date = \Carbon\Carbon::now();
$tmpFile = $request->file('file')->move(storage_path('temp-files'), $date->format('YmdHis') . '_' . $request->file('file')->getClientOriginalName());
Then I get move on null error on the last line shown.
Having never done this kind of thing before I admit I'm stabbing in the dark. Any help would be greatly appreciated.
After confirming in the comments that you want to check if the upload routine is being followed instead really uploading a file you can mock the facade File to see if the methods are called and with the right parameters (optional).
To mock a Facade in Laravel you can use the build in shouldReceive('method_name') method. In your situation you can add this before the call:
// should create new directory
File::shouldReceive('makeDirectory')
->once();
// should move the uploaded file to the dir
File::shouldReceive('move')
->once()
->andReturn( $fake_file );
You can read more about mocking facades here.

upload images to web service with laravel

I'm using Laravel 5.4 and Guzzle to upload files and images to another server.
I am using the following method on the client/server side
public function store (Request $request)
{
    $dataForm = $request->all();
    $Client = new Client();
        
    $response = $Client->post('http://localhost/WebService/public/api/client',
    [
       'multipart' =>
        [
            [
                'name' => 'UploadIMG',
                'filename' => 'image_org',
                'Mime-Type' => 'image_mime',
                'contents' => $ request->file('UploadIMG'),
            ],
        ]
            
    ]);
    $ response = $ response-> getBody () -> getContents ();
    return response () -> json (['error' => $ response]);
}
In the documentation part of the contents is 'contents' => fopen ('/ path / to / file', 'r') but I do not want to save the image but already get the request to be able to send, how is this possible?
the way I'm using comes a corrupted file in the web service.
I ran some tests with postman, so the problem is in the guzzle
With your current code for Guzzle, you're passing the $request->file('UploadIMG') which is an instance of Illuminate\Http\UploadedFile. For the 'contents' of the HTTP request, you need to pass the actual file itself into it.
Because the UploadedFile eventually extends SplFileInfo, my guess is to use its method of $request->file('UploadIMG')->openFile(). If you can't read it from there, then my second guess would be to save it temporarily then read that.

Resources