I'm trying to implement on the fly creating and streaming zip files in Kohana 3.3 using ZipStream (https://github.com/Grandt/PHPZip). I assumed that zip file would be streamed as soon as first image is added to zip, but it happens that download is stalled up until whole zip file is created and sent to user.
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Download extends Controller {
public function action_images()
{
require Kohana::find_file('vendor', 'ZipStream');
$zip = new ZipStream("images.zip");
foreach($images as $image)
{
$zip->addLargeFile($image);
}
$zip->finalize();
exit;
}
}
Apparently Kohana buffers output and that can be negated by adding this to download action.
while (ob_get_level() > 0) {
ob_end_clean();
}
Whole controller
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Download extends Controller {
public function action_images()
{
while (ob_get_level() > 0) {
ob_end_clean();
}
require Kohana::find_file('vendor', 'ZipStream');
$zip = new ZipStream("images.zip");
foreach($images as $image)
{
$zip->addLargeFile($image);
}
$zip->finalize();
exit;
}
}
Related
I am trying to play an audio file which is stored locally. I am using Xam.Plugin.SimpleAudioPlayer for playing audio. For UWP and Android, added the files in the Assets folder with the Build Action set to Content and Android Asset respectively.
My Code:
private void PlayAudio()
{
try
{
var stream = GetStreamFromFile("audio.mp3");
var audio = Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.Current;
audio.Load(stream);
audio.Play();
}
catch (Exception e)
{
Debug.WriteLine("exception:>>" + e);
}
}
Stream GetStreamFromFile(string filename)
{
var assembly = typeof(App).GetTypeInfo().Assembly;
var stream = assembly.GetManifestResourceStream("AudioPlay." + filename);
return stream;
}
But getting an exception in android and UWP, didn't check in IOS.
Android Exception:
[0:] exception:>>System.NullReferenceException: Object reference not set to an instance of an object.
at Plugin.SimpleAudioPlayer.SimpleAudioPlayerImplementation.Load (System.IO.Stream audioStream) [0x00050] in C:\dev\open\Xamarin-Plugins\SimpleAudioPlayer\SimpleAudioPlayer\Plugin.SimpleAudioPlayer.Android\SimpleAudioPlayerImplementation.cs:100
at AudioPlay.MainPage.PlayAudio () [0x00014] in F:\AudioPlay\AudioPlay\AudioPlay\MainPage.xaml.cs:63
I am using .mp3 file. Am I missing something in this implementation? Please help me to fix this issue?
You just need to directly put the mp3 file in share project . And call the method
var stream = GetStreamFromFile("xxx.mp3");
var audio = Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.Current;
audio.Load(stream );
audio.Play();
Stream GetStreamFromFile(string filename)
{
var assembly = typeof(App).GetTypeInfo().Assembly;
var stream = assembly.GetManifestResourceStream("yourprojectname." + filename);
return stream;
}
Update
I check your demo , and if you want to play mp3 file in your project. You need to set the build action of the mp3 as Embedded resource
Right click the mp3 file -> Property
try this For xamarin.android
var u = Android.Net.Uri.Parse("filepath");
MediaPlayer _player = MediaPlayer.Create(this, u);
_player.Start();
or
use XamarinMediaManager plugin
https://github.com/martijn00/XamarinMediaManager
The accepted answer does not work when attempting to load a resource from a project that is not the main Xamarin Forms project.
The solution is to use Android.AssetManager.Open() to get a Stream (I'm sure iOS has something similar). You'll need to use DependencyService to access this outside the Android project.
The MP3 files would be put in the Assets folder of the Android project. The audio files need to have Build Action: "Android Asset", not "Embedded Resource" as above.
Example:
Android Project has Assets/Audio/click.mp3
AndroidProject/AndroidAssetManager.cs
[assembly: Dependency (typeof (AndroidAssetManager))]
namespace App.Droid
{
public interface IAssetManager
{
Stream LoadAsset(string assetName);
...
}
public class AndroidAssetManager : IAssetManager
{
private readonly AssetManager _assets;
public AndroidAssetManager(AssetManager assets)
{
_assets = assets;
}
public Stream LoadAsset(string assetName)
{
return _assets.Open(assetName);
}
...
}
}
Shared/AudioPlayer.cs:
class AudioPlayer : IAudioPlayer
{
private IAssetManager AssetManager => DependencyService.Get<IAssetManager>();
private ISimpleAudioPlayer _clickPlayer;
public AudioPlayer()
{
_clickPlayer = CrossSimpleAudioPlayer.CreateSimpleAudioPlayer();
_clickPlayer.Load(AssetManager.Load("Audio/click.mp3"));
}
public void PlayClick()
{
_clickPlayer.Play();
}
}
laravel excel version 3.1
laravel version 5.6
i have over 100000 rows of data in excel file. I would like to import this data into my database.
In My controller.php
if(request()->file('fertilizer_import')) {
$import = new FertilizerImport();
$file = request()->file('fertilizer_import');
dispatch(new FertilizerImportJob($import, $file));
}
In my FertilizerImportJob.php
public function __construct($import, $file)
{
$this->import = $import;
$this->file = $file;
}
public function handle()
{
Excel::import($this->import, $this->file);
}
And then, I uploaded my excel file. It is enter one row in jobs table. I run php artisan make:queue but data is not enter my fertilizer table.
How can i do that? Please advice me.
You should Try to use chunk and queue in laravel/Maatwebsite
In controller file
public function importExcel()
{
$path = resource_path() . "/Houten.xlsx";
\Excel::import(new TestImport, $path);
return redirect('/')->with('success', 'All good!');
return back();
}
And in Your Import File app/Imports/testImports.php
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithStartRow;
use Illuminate\Contracts\Queue\ShouldQueue;
use Maatwebsite\Excel\Concerns\WithChunkReading;
class TestImport implements ToCollection, WithChunkReading, ShouldQueue,WithStartRow
{
public function collection(Collection $rows)
{
//do your insertion here. //no seprate job required
}
public function startRow(): int
{
return 1;
}
public function batchSize(): int
{
return 500;
}
public function chunkSize(): int
{
return 500;
}
}
Then set QUEUE_DRIVER=database and run the code. You will see one entry in jobs table. then you need to run this job. there are multiple ways to run any job. below is one
In your terminal
php artisan queue:restart
php artisan queue:listen
this will execute the code in collection function in chunks and will insert your data.
I currently have a worker thread loading a external swf file successfully. But how do I call a function in the loaded swf file ?
This is the class located in the external swf file.
package
{
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.utils.ByteArray;
public class BackgroundProcesses extends Sprite {
public function BackgroundProcesses()
{
super();
}
public function EncryptTheImage(_imageToEncrypte:Bitmap):ByteArray
{
// Encrypted the image here
var _imageInEncryptedBytes:ByteArray = new ByteArray();
return _imageInEncryptedBytes;
}
}
}
Here is my Flex Mobile mxml file:
import mx.events.FlexEvent;
protected function LoadWorkerSwfFile(event:FlexEvent):void
{
var workerLoader:URLLoader = new URLLoader();
workerLoader.dataFormat = URLLoaderDataFormat.BINARY;
workerLoader.addEventListener(Event.COMPLETE, loadComplete);
workerLoader.load(new URLRequest("BackgroundProcesses.swf"));
}
private function loadComplete(event:Event):void
{
var workerBytes:ByteArray = event.target.data as ByteArray;
var bgWorker:Worker = WorkerDomain.current.createWorker(workerBytes);
bgWorker.addEventListener(Event.WORKER_STATE, WorkerIsRunning);
bgWorker.start();
}
private function WorkerIsRunning(event:flash.events.Event):void
{
}
Any help is appreciated!
Someone else can correct me, but I don't think you can access another worker's properties and methods directly, nor do I think you are suppose to be able to by design. Instead, you're supposed to pass messages and data back and forth between them to communicate and send/get work results.
This may help: Communicating between workers
I am trying to nest two (or more) views using the following code. I am struggling to find a way to successfully nest these views without losing the final view content and passing it through the $this->content variable within the last layout, as it just returns an empty string.
core/Framework/Mvc/Controller/BaseActionController.php
This is a simple base controller which uses the $frame and $layout variables (so that they can be used within any controller extending this class). The idea is the frame is defined as the page starting with <!DOCTYPE html> and the layout is the HTML which gets displayed in the frame using <?= $this->content; ?>.
namespace Framework\Mvc\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class BaseActionController extends AbstractActionController
{
protected $frame;
protected $layout;
protected $layouts = array();
public function preDispatch() {...}
public function dispatch() {..}
public function postDispatch()
{
if ($this->frame !== null) {
$this->layouts[] = $this->frame;
}
if ($this->layout !== null) {
$this->layouts[] = $this->layout;
}
foreach ($this->layouts as $layout) {
$view = new ViewModel();
$layoutView = new ViewModel();
$layoutView->setTemplate($layout);
$layoutView->addChild($view);
}
}
}
module/Application/view/layout/frame.phtml
The <?= $this->content; ?> part within this template should echo out the layout.phtml template along with it's own <?= $this->content; ?>.
<?= $this->doctype(); ?>
<html>
<head>
<meta charset="utf-8">
<title>Woohoo, I'm a frame</title>
</head>
<body>
<?= $this->content; ?>
</body>
</html>
module/Application/view/layout/admin/layout.phtml
The $this->content variable should echo out the contents of the module/Users/view/users/test/index.phtml file. At this point, the variable returns an empty string.
<header>
<img class="logo" src="<?= $this->basePath() ?>/img/logo.png" alt="Company">
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
</header>
<section>
<?= $this->content; ?>
</section>
<footer>
<ul>
<li>Copyright</li>
<li>Sitemap</li>
<li>Privacy policy</li>
</ul>
</footer>
module/Users/view/users/test/index.phtml
<h1 class="page__title">Test</h1>
<p class="page__content">The final view</p>
Temporary solution (not very nice to write this in each action)
<?php
namespace Users\Controller;
use Framework\Mvc\Controller\BaseActionController;
use Zend\View\Model\ViewModel;
class TestController extends BaseActionController
{
public function indexAction()
{
$view = new ViewModel();
$view->setTemplate('users/test/index.phtml');
$adminView = new ViewModel();
// This layout is defined in the Application module.config.php file
$adminView->setTemplate('layout/admin');
$adminView->addChild($view);
return $adminView;
}
}
As above, my temporary solution is to choose the template the ViewModel() instance needs, manually. I notice $view->setTemplate(); works but without defining one, $view->getTemplate(); returns an empty string. I am not sure where, in Zend Framework 2, the default template is being defined so I can replicate this within the base controller.
I think the solution I have (temporarily) could work, the only issue being the manual $view->setTemplate('/path/to/my/template.phtml');. If I can replicate how Zend does this, then it should work correctly but I am at a loss passing the $this->content variable into the layout.phtml file with the contents being the final view.
UPDATE:
As suggested by Next Developer, I have added the following:
module/Application/Module.php
<?php
namespace Application;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
use Zend\Session\Container;
use Framework\Mvc\View\Http\TemplateInjector;
class Module
{
public function onBootstrap(MvcEvent $e)
{
$app = $e->getApplication();
$request = $app->getRequest();
$response = $app->getResponse();
$eventManager = $app->getEventManager();
$serviceManager = $app->getServiceManager();
$session = new Container('locale');
if (!$session->offsetExists('locale')) {
$session->offsetSet('locale', \Locale::acceptFromHttp($request->getServer('HTTP_ACCEPT_LANGUAGE')));
}
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
$serviceManager->get('translator')
->setLocale($session->locale)
->setFallbackLocale('en_GB');
$eventManager->getSharedManager()
->attach(
'Zend\Stdlib\DispatchableInterface',
MvcEvent::EVENT_DISPATCH,
new TemplateInjector(),
-80
);
}
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
}
core/Framework/Mvc/View/Http/TemplateInjector.php
<?php
namespace Framework\Mvc\View\Http;
use Zend\Mvc\MvcEvent;
use Zend\View\Model\ModelInterface as ViewModel;
class TemplateInjector
{
public function __invoke(MvcEvent $event)
{
$model = $event->getResult();
if (!$model instanceof ViewModel) {
return;
}
if ($model->getTemplate()) {
return ;
}
$controller = $event->getTarget();
if (!is_object($controller)) {
return;
}
// #todo: Clear this mess up
$namespace = explode('\\', ltrim(get_class($controller), '\\'));
$controllerClass = array_pop($namespace);
array_pop($namespace);
$moduleName = implode('/', $namespace);
$controller = substr($controllerClass, 0, strlen($controllerClass) - strlen('Controller'));
$action = $event->getRouteMatch()->getParam('action');
$model->setTemplate(strtolower($moduleName.'/'.$controller.'/'.$action.'.phtml'));
}
}
Any changes in the TemplateInjector doesn't seem to change the view, by this time it seems too late. It does however set the template on the view. When making a new instance of $view = new VidewModel(); it uses the template defined in the TemplateInjector class which should allow me to automate the layout process, but the scope of everything being set, it seems too late. I know I can access the controller, the view and the model in the TemplateInjector but no matter how I change the views or add children, it doesn't come out on the front end. If anyone could provide a working example, that would be really helpful.
I think the best would be in your case is to override the default template injector with your own. Take a look at this post http://blog.igorvorobiov.com/2014/10/18/creating-a-custom-template-injector-to-deal-with-sub-namespaces-in-zend-framework-2/. It explains pretty much well how to create and setup your own template injector.
Basically, you need to create an event listener and attach it to the event MvcEvent::EVENT_DISPATCH triggered by the current controller. Inside the event listener you can put the logic which determines a path to the requested template. In your case, you can get your child view model by calling $model->getChildrenByCaptureTo('capture'); and set the template name to it as you want.
The default logic which resolves template names can be found here Zend\Mvc\View\Http\InjectTemplateListener::injectTemplate
UPDATE:
Upon discussion with #Titanium, this solution was found to be the correct one.
I have tried to understand you problem, so here's another solution to it.
Replace the previous template injector code with this one:
class TemplateInjector
{
public function __invoke(MvcEvent $e)
{
$model = $e->getResult();
if (!$model instanceof ViewModel)
{
return;
}
$controller = $e->getTarget();
if (!is_object($controller))
{
return ;
}
if (!$controller instanceof LayoutTemplateProviderInterface)
{
return ;
}
$frameTemplate = $controller->getFrameTemplate();
if ($frameTemplate !== null)
{
$e->getViewModel()->setTemplate($controller->getFrameTemplate());
}
$layoutTemplate = $controller->getLayoutTemplate();
if ($layoutTemplate !== null)
{
$model = $e->getResult();
$layoutModel = new ViewModel();
$layoutModel->setTemplate($controller->getLayoutTemplate());
$layoutModel->addChild($model);
$e->setResult($layoutModel);
}
}
}
Now, you need to define interface which your base controller class should implement in order to tell the system that you want to use custom templates:
interface LayoutTemplateProviderInterface
{
public function getFrameTemplate();
public function getLayoutTemplate();
}
Then in your base controller you should implement the interface like so:
abstract class BaseController extends AbstractActionController implements LayoutTemplateProviderInterface
{
private $frameTemplate = 'layout/layout';
private $layoutTemplate = 'layout/admin';
public function getFrameTemplate()
{
return $this->frameTemplate;
}
public function getLayoutTemplate()
{
return $this->layoutTemplate;
}
protected function setFrameTemplate($name)
{
$this->frameTemplate = $name;
}
protected function setLayoutTemplate($name)
{
$this->layoutTemplate = $name;
}
}
The last thing is to change the priority at which our template injector is getting executed.
$eventManager->getSharedManager()
->attach(
'Zend\Stdlib\DispatchableInterface',
MvcEvent::EVENT_DISPATCH,
new TemplateInjector(),
-91
);
So, our template injector will be executed right after the default one, this allows us to avoid resolving the template name and rely on the default logic.
After all this, your action looks like this:
public function testAction()
{
return new ViewModel();
}
As you can see you don't have to create nesting views here, it will be done automatically by TemplateInjector.
If you need to change frame template name or layout template within an action you can do it like so:
$this->setFrameTemplate("new/template");
$this->setLayoutTemplate("new/template");
Let me know if this solution solves your problem so I can remove the first one to make this post clearer.
We're making an ASP.Net MVC app that needs to be able to generate a PDF and display it to the screen or save it somewhere easy for the user to access. We're using PdfSharp to generate the document. Once it's finished, how do we let the user save the document or open it up in a reader? I'm especially confused because the PDF is generated server-side but we want it to show up client-side.
Here is the MVC controller to create the report that we have written so far:
public class ReportController : ApiController
{
private static readonly string filename = "report.pdf";
[HttpGet]
public void GenerateReport()
{
ReportPdfInput input = new ReportPdfInput()
{
//Empty for now
};
var manager = new ReportPdfManagerFactory().GetReportPdfManager();
var documentRenderer = manager.GenerateReport(input);
documentRenderer.PdfDocument.Save(filename); //Returns a PdfDocumentRenderer
Process.Start(filename);
}
}
When this runs, I get an UnauthorizedAccessException at documentRenderer.PdfDocument.Save(filename); that says, Access to the path 'C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\report.pdf' is denied. I'm also not sure what will happen when the line Process.Start(filename); is executed.
This is the code in manager.GenerateReport(input):
public class ReportPdfManager : IReportPdfManager
{
public PdfDocumentRenderer GenerateReport(ReportPdfInput input)
{
var document = CreateDocument(input);
var renderer = new PdfDocumentRenderer(true, PdfSharp.Pdf.PdfFontEmbedding.Always);
renderer.Document = document;
renderer.RenderDocument();
return renderer;
}
private Document CreateDocument(ReportPdfInput input)
{
//Put content into the document
}
}
Using Yarx's suggestion and PDFsharp Team's tutorial, this is the code we ended up with:
Controller:
[HttpGet]
public ActionResult GenerateReport(ReportPdfInput input)
{
using (MemoryStream stream = new MemoryStream())
{
var manager = new ReportPdfManagerFactory().GetReportPdfManager();
var document = manager.GenerateReport(input);
document.Save(stream, false);
return File(stream.ToArray(), "application/pdf");
}
}
ReportPdfManager:
public PdfDocument GenerateReport(ReportPdfInput input)
{
var document = CreateDocument(input);
var renderer = new PdfDocumentRenderer(true,
PdfSharp.Pdf.PdfFontEmbedding.Always);
renderer.Document = document;
renderer.RenderDocument();
return renderer.PdfDocument;
}
private Document CreateDocument(ReportPdfInput input)
{
//Creates a Document and puts content into it
}
I'm not familar with PDF sharp but for MVC is mostly done via built in functionality. You need to get your pdf document represented as an array of bytes. Then you'd simply use MVC's File method to return it to the browser and let it handle the download. Are there any methods on their class to do that?
public class PdfDocumentController : Controller
{
public ActionResult GenerateReport(ReportPdfInput input)
{
//Get document as byte[]
byte[] documentData;
return File(documentData, "application/pdf");
}
}