Reading large user provided file from emscripten, chunk at a time - file-io

I am looking for an API that let me read file provided via (or any other method that allows to access users files from browser) chunk at a time. I'm reading large files, so I don't want to load entire file to memory.
My use case is, I'm using ffmpeg library compiled with emcc and I wan't to process multimedia files by it. I could implement my own AVIOContext but to do that, I would need equivalent of C functions fread and fseek.
I was looking at FS API with WORKERFS file system type, but it is not clear to me that I could mount it from worker thread with File object from DOM.

I was able to mount file with WORKERFS from worker thread.
Minimal example:
main.html:
<html>
<head>
<script>
const worker = new Worker("worker.js");
function onClick() {
const f = document.getElementById("in-file").files[0];
worker.postMessage([ f ]);
}
</script>
</head>
<body>
<input type="file" id="in-file" />
<input type="button" onClick="onClick()" value="ok" />
</body>
</html>
worker.js
onmessage = function(e) {
const f = e.data[0];
FS.mkdir('/work');
FS.mount(WORKERFS, { files: [f] }, '/work');
console.log(Module.read_file('/work/' + f.name));
}
self.importScripts('hello.js');
hello.js is compiled hello.cpp with
(emcc --bind -lworkerfs.js -o hello.js hello.cpp -s WASM=1):
#include <cstdio>
#include <string>
#include <iostream>
#include <fstream>
#include <emscripten/bind.h>
using namespace emscripten;
std::string read_file(const std::string &fn)
{
std::ifstream f(fn);
std::string line;
std::getline(f, line);
return line;
}
EMSCRIPTEN_BINDINGS(hello) {
function("read_file", &read_file);
}

Related

Facebook Pixel integration on Vue 2.6 with env & custom index templates

FB Pixel is generally blocked when you add meta tag or script dynamically.
And if you have different pixel accounts for your staging and production environments you need to add meta tag & script dynamically getting id & content from env files.
The result is
Failed to load resource: net::ERR_BLOCKED_BY_CLIENT
How to achieve run FB pixel successfully?
To achieve this, a solution is you need to use different index.html templates for different environments.
In default, vue cli using public/index.html file to build app. But we can change it using vue.config.js as below.
module.exports = {
pluginOptions: {
i18n: {
locale: "en",
fallbackLocale: "en",
localeDir: "locales",
enableInSFC: false
}
},
pages: {
index: {
entry: "src/main.js",
template: process.env.VUE_APP_INDEX_TEMPLATE,
filename: "index.html"
}
},
transpileDependencies: ["vuetify"]
};
as you can see on template, we are using env variables.
and we need to add this variables to all env files, in my case I am using
.env.staging
.env.development
.env.production
and the keys in order
VUE_APP_INDEX_TEMPLATE=public/index_staging.html
VUE_APP_INDEX_TEMPLATE=public/index_development.html
VUE_APP_INDEX_TEMPLATE=public/index.html
And we need to add FB Pixel meta tag & script files to the templates according to its own pixel account credentials inside the head tags statically.
<head>
...
<!-- Facebook Pixel Code -->
<meta
name="facebook-domain-verification"
content="FB_DOMAIN_VERIFICATION_CODE_HERE_STATICALLY"
/>
<script>
!(function(f, b, e, v, n, t, s) {
if (f.fbq) return;
n = f.fbq = function() {
n.callMethod
? n.callMethod.apply(n, arguments)
: n.queue.push(arguments);
};
if (!f._fbq) f._fbq = n;
n.push = n;
n.loaded = !0;
n.version = "2.0";
n.queue = [];
t = b.createElement(e);
t.async = !0;
t.src = v;
s = b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t, s);
})(
window,
document,
"script",
"https://connect.facebook.net/en_US/fbevents.js"
);
fbq("init", "FB_PIXEL_ID_HERE_STATICALLY");
fbq("track", "PageView");
</script>
<noscript
><img
height="1"
width="1"
style="display:none"
src="https://www.facebook.com/tr?id=FB_PIXEL_ID_HERE_STATICALLY&ev=PageView&noscript=1"
/></noscript>
<!-- End Facebook Pixel Code -->
</head>

How to replace some values inside a specific tag in a index.html file using a cypress automation test

Currently, I'm working with Cypress test automation. I have an index.html file inside cypress/downloads/sample/index.html. The index.html file has the below structure.
<html>
<head>
<style type="text/css">
</style>
</head>
<body>
<script src="https://test"></script>
<script src="https://test2"></script>
<!-- sample Config -->
<script>
const authConfig = {
clientID: "sample value",
signInRedirectURL: "sample value",
serverOrigin: "sample value"
};
</script>
</body>
</html>
I will get copy the content inside the script tag which will be displayed in an application UI using a button click for the copy operation so the copied content will be as below
<script>
const authConfig = {
clientID: "abcd1234",
signInRedirectURL: "https://localhost:8000",
serverOrigin: "https://localhost:8000"
};
</script>
Method written for copy and paste operation is as below:
static CopyConfigs() {
cy.get(COPY_ICON).click();
cy.wait(7000);
}
static pasteoperation(Location){
cy.task("getClipboard").then((value) => {
cy.writeFile(Location + "/sample/index.html", value);
});
}
writeFile will replace the whole index.html file content
Need help on
I want to replace(paste) the content copied to the index.html file by replacing only the script tag(related to authConfig) content inside the index.html file without replacing the whole index.html file content. So that the values for clientID, signInRedirectURL, and serverOrigin inside the script tag of index.html file will have the new values. Is it possible to read the index.html file and capture the script tag and replace the <script> tag content using Cypress automation? Appreciate your support on how to achieve this.

Using ports with elm-app

I'm trying to use ports with elm-app. Previously I used elm-live and a vanilla setup, and was able to insert ports like this:
index.html
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<script>
window.addEventListener("load", function(event) {
var app = Elm.Main.fullscreen(localStorage.session || null);
app.ports.storeSession.subscribe(function(session) {
localStorage.session = session;
});
...
This worked, and elm-live seemed to embed elm.js in the <head> of index.html.
When I try to use this setup for ports with create-elm-app, however, the compiled javascript is embedded at the bottom of the <body>, so adding the <script> as I did results in this:
(index):68 Uncaught ReferenceError: Elm is not defined
at (index):68
What is the best way to embed the JS ports?
The halfzebra/create-elm-app project sets things up a little differently. You'll have to modify the src/index.js file like the example shows in the documentation on Javascript Interop
import './main.css';
import { Main } from './Main.elm';
import registerServiceWorker from './registerServiceWorker';
var app = Main.embed(document.getElementById('root'));
registerServiceWorker();
// ports related code
app.ports.windowTitle.subscribe(function(newTitle){
window.document.title = newTitle;
});

conditional #import in .less or no error when file missing

I need to conditionally import a file during a particular type of build. Using grunt-contrib-jshint#0.7.0 which is on top of less#1.4.2
What I tried thus far...
Trying to use protected mixins to determine the type of build I require and namely, to skip imports of certain less files that break in dev mode.
#isProduction: 1;
...
.getImports() when (#isProduction = 1){
}
.getImports() {
#import "productionStyles";
}
...
.getImports();
however, this seems to fail and it tries to import and parse productionStyles.less all the time. I guess protected mixins does not cover #import, so how would you solve that?
I also tried
#productionStyles: "productionStyles"; // or 0
...
#productionStyles: 0;
.getImports() when not (#productionStyles = 0){
#import "#{productionStyles}";
}
...
to same avail, it will try to import it anyway >> FileError: '0.less' wasn't found in ....
I am starting to think it will need a bigger refactor where devStyles and productionStyles are both a thing and I just switch between them - it's just that productionStyles was an addition that can only compile after a full build due to deps and I would much rather solve this by compiling conditionally.
I can also move away from using grunt-contrib-jshint and write my own less parser but would like to explore the built-in options first.
As the productionStyle.less references several files that are not in the file system, is it possible to ignore the #imports that fail and continue building? I would prefer not to disable error checking/break on all errors due to possible parser errors elsewhere...
I've solved your problem using switch parameter:
index.html
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet/less" type="text/css" href="style.less" />
<script src="less.js" type="text/javascript"></script>
</head>
<body>
[foo]
</body>
</html>
style.less
.mixin(production) {
#import "test.less";
background: #color;
}
.mixin(dev) {
background: green;
}
html {
.mixin(production);
}
test.less
#color: red;
less.js is less v1.4.1 downloaded straight from project page.
Code about should result in red background.
Switching to html { .mixin(dev); } disables #import and background turns green.
It's possible that your solution would work, too, but you have errors in HTML or something like that - I haven't checked that.

jQuery not defined + MVC4

Im creating the below MVC view that has got some jquery script in it.
However this script is not getting executed. Getting jQuery undefined error.
I want to write including script directly in view instead of using layout page.
Can somebody advise what am I doing wrong here?
#{
ViewBag.Title = "FileUpload";
}
<html lang="en">
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title - What up boyeez!</title>
<meta name="viewport" content="width=device-width" />
<script src="~/Scripts/jquery-ui-1.10.0.min.js"></script>
<h2>FileUpload</h2>
#using (Html.BeginForm("UploadFile", "FileUpload", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary();
<ol>
<li class="lifile">
<input type="file" id="fileToUpload" name="file" />
<span class="field-validation-error" id="spanfile"></span>
</li>
</ol>
<input type="submit" id="btnSubmit" value="Upload" />
}
</body>
</html>
<script type="text/jscript">
(function ($) {
function GetFileSize(fileid) {
try {
var fileSize = 0;
if ($.browser.msie) {
var objFSO = new ActiveXObject("Scripting.FileSystemObject");
var filePath = $("#" + fileid)[0].value;
var objFile = objFSO.getFile(filePath);
var fileSize = objFile.size;
fileSize = fileSize / 1048576;
}
else {
fileSize = $("#", fileid)[0].files[0].size
fileSize = file / 1048576;
}
return fileSize;
}
catch (e) {
alter("Error is: " + e);
}
}
function getNameFromPath(strFilepath) {
debugger;
var objRE = new RegExp(/([^\/\\]+)$/);
var strName = objRE.exec(strFilepath);
if (strName == null) {
return null;
}
else {
return strName[0];
}
}
$("#btnSubmit").live("click", function () {
debugger;
if ($('#fileToUpload').val == "") {
$("#spanfile").html("Please upload file");
return false;
}
else {
return checkfile();
}
});
function checkfile() {
var file = getNameFromPath($("#fileToUpload").val());
if (file != null) {
var extension = file.subst((file.last('.') + 1));
switch (extension) {
case 'jpg':
case 'png':
case 'gif':
case 'pdf':
flag = true;
break;
default:
flag = false;
}
}
if (flag == false) {
$("#spanfile").text("You can upload only jpg, png, gif, pdf extension file");
return false;
}
else {
var size = GetFileSize('fileToUpload');
if (size > 3) {
$("#spanfile").text("You can upload file up to 3 MB");
return false;
}
else {
$("#spanfile").text("");
}
}
}
$(function () {
debugger;
$("#fileToUpload").change(function () {
checkfile();
});
});
})(jQuery);
You are missing a reference to jquery itself. You probably also want a css file for jquery ui:
<link rel="stylesheet" href="css/themename/jquery-ui.custom.css" />
<script src="js/jquery.min.js"></script>
<script src="js/jquery-ui.custom.min.js"></script>
See the "Basic Overview: Using jQuery UI on a Web Page" section on the jquery-ui learning docs for full details of how to use and customise jquery ui.
Razor techniques for jquery files
To make your life easier in your view template, you could use the scripts render function:
#Scripts.Render("~/Scripts/jquery-1.9.1.min.js")
#Scripts.Render("~/Scripts/jquery-ui-1.10.0.min.js")
In itself, not too impressive: the syntax is slightly more expressive and 5 characters shorter, that's all.
But it leads you into bundles (references at the end), which are really what you should be using.
Bundles are awesome
Bundles allow you to:
Group dependent files: grouping js and/or css files together reduces the chances of this happening, and also means you can "modularise" your own scripts into multiple files in one folder.
Increase performance: Send out everything inside a single Bundle in a single file - speeding up load times for clients by reducing the number of http requests from the browser
Help development: Use non-minified javascripts (and css) for debugging during development
Publish without changes to code: Use the minified scripts for live deployment
Use in-built minifying for your own scripts
Optimise client experience: Use CDNs for standard scripts like jquery (which is better for your users)
Upgrade easily: Not have to change code when you update your version numbers for things like jquery through NuGet by use of the {version} wildcard (as below)
Example:
// This is usually in your MVC 4 App_Start folder at App_Start\BundleConfig
public class BundleConfig {
public static void RegisterBundles(BundleCollection bundles) {
// Example with full use of CDNs in release builds
var jqueryCdnPath = "https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js";
bundles.Add(new ScriptBundle("~/bundles/jquery", jqueryCdnPath).Include("~/Scripts/jquery-{version}.js"));
And in your razor file you only need a tiny change:
#Scripts.Render("~/bundles/jquery");
This will:
send out the full jquery script during debugging
send out the minified script for a release build
even minify your own bundles such as #Scripts.Render("~/bundles/myScripts"); for live builds
Bundle details
Under the hood bundles will use the CDNs, or minify your own scripts as well, or send already minified files (like jquery-1.9.1.min.js) during release builds, but you can control this by using bundles.UseCdn and BundleTable.EnableOptimizations inside your RegisterBundles method. By using this along with AppSettings in your web.config you can have very close control so that you could even send out debugging scripts for certain users on a live site.
Also note the use of {version} in the bundle configuration.
You can include multiple scripts in a bundle as well:
bundles.Add(new ScriptBundle("~/bundles/jqueryWithUi")
.Include(
"~/Scripts/jquery-{version}.js",
"~/Scripts/jquery-ui-{version}.js"
));
This razor command will now send out both files for you:
#Scripts.Render("~/bundles/jquery");
And you can use bundles for css:
bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
"~/Content/themes/base/jquery.ui.core.css",
"~/Content/themes/base/jquery.ui.resizable.css",
"~/Content/themes/base/jquery.ui.selectable.css",
"~/Content/themes/base/jquery.ui.accordion.css",
"~/Content/themes/base/jquery.ui.autocomplete.css",
"~/Content/themes/base/jquery.ui.button.css",
"~/Content/themes/base/jquery.ui.dialog.css",
"~/Content/themes/base/jquery.ui.slider.css",
"~/Content/themes/base/jquery.ui.tabs.css",
"~/Content/themes/base/jquery.ui.datepicker.css",
"~/Content/themes/base/jquery.ui.progressbar.css",
"~/Content/themes/base/jquery.ui.theme.css"));
References:
www.asp.net - Bundling and Minification
You're loading the jQuery UI library without loading the jQuery library.
<script src="~/Scripts/path/to/jquery"></script
<script src="~/Scripts/jquery-ui-1.10.0.min.js"></script
I was having the same problem of client side validation not working. I brought up the JavaScript console in Chrome and saw I was receiving an error stating "JQuery was not defined.".
Turns out I had some code in my View that was causing problems with jQuery not loading.
Recommendation to others who come across this, check your JS console in your browser to ensure you are not getting a JQuery error.