Phonegap: Photo not uploading - api

I'm trying to create a very basic photo upload feature. I've followed a lot of tutorials and examples online but I'm having some issues in actually getting it to work.
Currently I receive the following errors:
2012-03-26 17:37:02.107 Upload[84710:13403] fileData length: 72154
2012-03-26 17:37:02.119 Upload[84710:13403] File Transfer Error: unsupported URL
2012-03-26 17:37:02.121 Upload[84710:13403] [INFO] Error in error callback: org.apache.cordova.filetransfer1 = ReferenceError: Left side of assignment is not a reference.
This is my Phonegap HTML file:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>File Transfer Example</title>
<script type="text/javascript" charset="utf-8" src="cordova-1.5.0.js"></script>
<script type="text/javascript" charset="utf-8">
// Wait for PhoneGap to load
document.addEventListener("deviceready", onDeviceReady, false);
// PhoneGap is ready
function onDeviceReady() {
// Do cool things here...
}
function getImage() {
// Retrieve image file location from specified source
navigator.camera.getPicture(uploadPhoto, function(message) {
alert('get picture failed');
},{
quality: 50,
destinationType: navigator.camera.DestinationType.FILE_URI,
sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY
}
);
}
function uploadPhoto(imageURI) {
var options = new FileUploadOptions();
options.fileKey="file";
options.fileName=imageURI.substr(imageURI.lastIndexOf('/')+1);
options.mimeType="image/jpeg";
var params = new Object();
params.value1 = "test";
params.value2 = "param";
options.params = params;
options.chunkedMode = false;
var ft = new FileTransfer();
ft.upload(imageURI, "hosting.domain.co.uk/ios/upload.php", win, fail, options);
}
function win(r) {
console.log("Code = " + r.responseCode);
console.log("Response = " + r.response);
console.log("Sent = " + r.bytesSent);
alert(r.response);
}
function fail(error) {
alert("An error has occurred: Code = " = error.code);
}
</script>
</head>
<body>
<button onclick="getImage();">Upload a Photo</button>
</body>
</html>
And this is my upload.php file:
<?php
print_r($_FILES);
$new_image_name = "namethisimage.jpg";
move_uploaded_file($_FILES["file"]["tmp_name"], "/var/www/vhosts/domain.co.uk/subdomains/hosting/httpdocs/ios/uploads".$new_image_name);
?>
Is there anything obvious that I'm doing wrong?
Thanks a lot
Jon

You are using fileURI to upload the photo that is why you are getting the unsupported file format error. This is because the fileURI will be something of the format file://localhost/xx1.jpg. This will be unsupported by the uploader function on the server side.
Javascript can't access the native file system
Javascript does not have direct access to the underlying file system therefore it cannot upload via file transfer in case of phonegap.
The Solution
Your best bet is to instead upload the base64 encoded string for the image. You can obtain the base64 encoded image by using the option navigator.camera.DestinationType.DATA_URL for destinationType. This will return the base64 encoded string. And this can be easily sent over json to the server with the associated metadata like jpg or png format and filename etc.
Take a look here of a successful use of phonegap and an online image hosting facility provided by imgur.
Good Luck and Cheers

Related

Autodesk Forge Viewer API not working in React Native

A few days ago, I was trying to build Autodesk forge viewer API with react native by following this example:
https://forge.autodesk.com/blog/forge-react-native-au-talk
It works well. It used viewer v2.17, I up to viewer v7 but unfortunately, It doesn't show anything. I caught an error: Cannot read property 'texture' of null, when I use line viewer.start();
Please, help
Looking at your code it seems to me you're not using the viewer options properly on initializing.
The way to define the access token is by a callback as per the sample posted by Bryan.
Using the code below the viewer loaded in fine.
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<link rel="stylesheet" href="https://developer.api.autodesk.com/derivativeservice/v2/viewers/style.min.css?v=v7.*" type="text/css">
<script src="https://developer.api.autodesk.com/derivativeservice/v2/viewers/three.min.js?v=v2.17"></script>
<script src="https://developer.api.autodesk.com/derivativeservice/v2/viewers/viewer3D.js?v=v7.*"></script>
</head>
<body style="margin:0">
<div id="viewer"></div>
</body>
<script>
var viewer = null;
function initializeViewer(urn, token) {
var options = {
env: "AutodeskProduction",
getAccessToken: function(onTokenReady) {
var token = 'access token provided by 2 legged api';
var timeInSeconds = 3600; // Use value provided by Forge Authentication (OAuth) API
onTokenReady(token, timeInSeconds);
}
}
Autodesk.Viewing.Initializer(options, () => {
try {
viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('viewer'));
viewer.start();
console.log('viewer loaded');
} catch (err) {
alert(err)
}
});
function onDocumentLoadSuccess(doc) {
var viewables = doc.getRoot().getDefaultGeometry();
viewer.loadDocumentNode(doc, viewables).then(i => {
// documented loaded, any action?
});
}
function onDocumentLoadFailure(viewerErrorCode) {
console.error('onDocumentLoadFailure() - errorCode:' + viewerErrorCode);
}
}
</script>

Export Html to Pdf using JsReport in Asp.net core

I have a html page with images, tables and some styling with Bootstrap 4. I tried to convert the pages to pdf using the JsReportMVCService, the pdf doesnot load with the proper css class from bootstrap.
HTML CONTENT
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>WeekelyReport</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
</head>
<body>
<div class="jumbotron">
<h1> Hello John Doe,</h1>
<p>
This is a generic email about something.<br />
<br />
</p>
</div>
</body>
</html>
ASP.NET CORE IMPLEMENTATION
var generatedFile = await GeneratePDFAsync(htmlContent);
File.WriteAllBytes(#"C:\temp\hello.pdf", generatedFile);
async Task<byte[]> GeneratePDFAsync(string htmlContent)
{
var report = await JsReportMVCService.RenderAsync(new RenderRequest()
{
Template = new Template
{
Content = htmlContent,
Engine = Engine.None,
Recipe = Recipe.ChromePdf
}
});
using (var memoryStream = new MemoryStream())
{
await report.Content.CopyToAsync(memoryStream);
return memoryStream.ToArray();
}
}
How my Pdf Looks after the conversion to PDF.
It is possible to convert to pdf with the same bootstrap 4 layout? or am i missing something during the conversion here?
The pdf printing uses print media type and the bootstrap has quite different styles for printing. This causes that the pdf looks different than html, but it looks the same as you would print it. I would generally not recommend using responsive css framework as bootstrap for printing static pdf, but it is of course your choice.
To make your example looking the same on pdf you just need to change the media type on the chrome settings.
var report = await JsReportMVCService.RenderAsync(new RenderRequest()
{
Template = new Template
{
Content = htmlContent,
Engine = Engine.None,
Recipe = Recipe.ChromePdf,
Chrome = new Chrome {
MediaType = MediaType.Screen,
PrintBackground = true
}
}
});
make sure you have the latest jsreport.Types#2.2.2

URL.createObjectURL(mediaSource) - play back video from URL - MOOV atom - Elastic Transcoder

I am trying to play back a video (currently hosted on S3 with public access) by creating a blob URL.
I have used Elastic Transcoder to encode the video since it is supposed to set the MOOV atom to the top (beginning).
I am unable to get the code to work but also found a working example: link here
Here is my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<video controls></video>
<script>
var video = document.querySelector('video');
var assetURL = 'https://ovation-blob-url-test.s3.amazonaws.com/AdobeStock_116640093_Video_WM_NEW.mp4';
// Need to be specific for Blink regarding codecs
// ./mp4info frag_bunny.mp4 | grep Codec
var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {
var mediaSource = new MediaSource;
//console.log(mediaSource.readyState); // closed
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen);
} else {
console.error('Unsupported MIME type or codec: ', mimeCodec);
}
function sourceOpen (_) {
//console.log(this.readyState); // open
var mediaSource = this;
var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
fetchAB(assetURL, function (buf) {
sourceBuffer.addEventListener('updateend', function (_) {
mediaSource.endOfStream();
video.play();
//console.log(mediaSource.readyState); // ended
});
sourceBuffer.appendBuffer(buf);
});
};
function fetchAB (url, cb) {
console.log(url);
var xhr = new XMLHttpRequest;
xhr.open('get', url);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
cb(xhr.response);
};
xhr.send();
};
</script>
</body>
</html>
What am I doing wrong? I looked at tools ie.e MP4Box or QT-FastStart but they seem to be kind of old school. I would also be willing to change from MP4 to M3U8 playlist but then I don't know what MIME types to use.
At the ned of the day I am trying to play back a video/stream and hide the URL (origin) potentially using blob.
Thank you guys!
So, first, even though this code seems to be taken from mozilla documentation site, there are a few issues - you are not checking the readyState before calling endOfStream thus the error you get is valid, secondly, the play() call is blocked by the autoplay policy changes. If you add an error handler, you will actually see that the appendBuffer fails. Here is the updated snippet:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<video controls></video>
<script>
var video = document.querySelector('video');
var assetURL = 'https://ovation-blob-url-test.s3.amazonaws.com/AdobeStock_116640093_Video_WM_NEW.mp4';
// Need to be specific for Blink regarding codecs
// ./mp4info frag_bunny.mp4 | grep Codec
var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {
var mediaSource = new MediaSource;
//console.log(mediaSource.readyState); // closed
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen);
} else {
console.error('Unsupported MIME type or codec: ', mimeCodec);
}
function sourceOpen (_) {
//console.log(this.readyState); // open
var mediaSource = this;
var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
fetchAB(assetURL, function (buf) {
sourceBuffer.addEventListener('updateend', function (_) {
// console.log(mediaSource.readyState); // ended
if (mediaSource.readyState === "open") {
mediaSource.endOfStream();
video.play();
}
});
sourceBuffer.addEventListener('error', function (event) {
console.log('an error encountered while trying to append buffer');
});
sourceBuffer.appendBuffer(buf);
});
};
function fetchAB (url, cb) {
console.log(url);
var xhr = new XMLHttpRequest;
xhr.open('get', url);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
cb(xhr.response);
};
xhr.send();
};
</script>
</body>
</html>
So lets advance to next issue - the actual error. So, using chrome://media-internals/ we can see that the video actually fails to load do to incompatibility with the ISOBMFF format:
I am not familiar with Elastic Transcoder, but it seems that is it not producing an mp4 file suitable for live streaming. Also, if using mse, putting moov at the beginning is not enough, the video actually has to meet all of the ISOBMFF requirements - see chapters 3. and 4.
The working sample you mentioned is not a valid comparison since it uses the blob for the src, where the ISOBMFF rules do not apply. If it is fine for you to go that way, don't use MSE and put the blob directly in the src. If you need MSE, you have to mux it correctly.
Ok, so I got the original code example to work by encoding my MP4 videos with ffmpeg:
ffmpeg -i input.mp4 -vf scale=1920:1080,setsar=1:1 -c:v libx264 -preset medium -c:a aac -movflags empty_moov+default_base_moof+frag_keyframe output.mp4 -hide_banner
Important is: -movflags empty_moov+default_base_moof+frag_keyframe
This setup also scales the video to 1920x1080 (disregarding any aspect ratio of the input video)
However, based on the comments of the original post, I do believe there might be a more efficient way to generate the blob url and ingest into a video tag. This example was copied straight from https://developer.mozilla.org.
If anyone comes up with a better script (not over-engineered), please post it here.
Thank you #Rudolfs Bundulis for all your help!

Open URL in new safari tab - safari extention

generaly i ask exactly the same question as here:
Safari extension: Event for a completely new tab?
in this answer (case 3) he guide to listen click event inside inject.js.
can someone show this implementation?
Here's an implementation I used for one of my previous extensions:
Create a global.html file, and inside the Extension Builder, select that file under the Extension Global Page section:
Source for global.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>My Extension</title>
</head>
<body>
<script>
function messageHandler(event) {
var newTab = null;
var url = null;
if (event.name === "open_new_tab") {
url = event.message;
newTab = safari.application.activeBrowserWindow.openTab();
newTab.url = url;
}
}
safari.application.addEventListener("message", messageHandler, false);
</script>
</body>
</html>
Create an extension.js file, and add it to the Injected Extension Content -> End Scripts section:
Source for extension.js:
(function() {
// ... rest of you extension code
openNewTabWithUrl("http://google.com")
function openNewTabWithUrl(url) {
safari.self.tab.dispatchMessage("open_new_tab", url);
}
}());
This will send a message containing a URL from your extension.js to global.html, which will pick up the message and open the new tab.

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.