why does this property return undefined? - javascript

I'm working on an AMR codec in Javascript and i cannot seem to get a file reference to be recognized by the decoder module. Here is a sample of my code:
reader.onload = (function (file) {
return function (e) {
var extension = file.name.split(".")[1];
if (extension === "amr") {
console.log("in try");
var stuff = e.target.result;
console.log(stuff.length);
var jigg = new AMR();
jigg.benchmark == 'true';
console.log(jigg); //jigg is defined, it's an instance of amr
// let's call some amr functions...
var dcoded = jigg.decode(stuff);
AMR.util.play(dcoded); //this throws an 'undefined' error, indicating that 'dcoded' is undefined.
} else if (extension == "wav") {
var data = e.target.result;
encodeWAV(data);
} else if (extension == "pcm" && isTypedArray) {
encodeRawPCM(new Int16Array(e.target.result));
}
};
})(f);
if ( !! isTypedArray) {
reader.readAsArraybuffer(f);
return;
}
// Read the file as a Binary String
reader.readAsBinaryString(f);
}
I have commented the line where the trouble occurs.
AMR.util.play(dcoded);

Related

JavaScript - file to bytes array

I'm trying to get a script to work, which is called sfo.js.
The repo mentions only this usage:
keys = parse_sfo(Some_ArrayBuffer);
console.log(keys['TITLE']);
Looking into the sfo.js, parse_sfo has the sfoBytes argument.
From this I've concluded the sfoBytes argument needs to be an arraybuffer of file bytes.
I've tried to make a script that parses the SFO file into a array of bytes:
<script src="sfo.js"></script>
<script>
function stringToArrayBuffer(str) {
var buf = [];
for (var i=0, strLen=str.length; i<strLen; i++) {
buf[i] = str.charCodeAt(i);
}
console.log(buf);
return buf;
}
function testing(url) {
var request = new XMLHttpRequest();
request.open('GET', url, false);
request.send(null);
if (request.status === 200) {
console.log(request.response);
var response = request.response;
var array = stringToArrayBuffer(response);
return array;
} else {
alert('Error!');
}
}
var data = testing('param.sfo');
var sfo = parse_sfo(data);
</script>
That throws an error in the console:
Uncaught RangeError: byte length of Uint32Array should be a multiple of 4 at new Uint32Array (<anonymous>)
at readUint32At (sfo.js:20)
at parse_sfo (sfo.js:113)
at (index):29
I'm pretty sure I'm doing something wrong. Does anybody understand how I can make the script work properly?
I have a sample file for param.sfo: https://filebin.net/gghosrp6u93jn7y8 (if linking to a download is not allowed please let me know)
Ok, finally the working example.
I've found a small param.sfo file in the internet.
Notes:
there are 2 versions of file reader: local and remote
in the snippet below you can test both (I've added my param.sfo as an external link to test 'remote'). To test 'local' you just need to select any sfo file from you PC.
as a result I show all the keys, not only 'TITLE' (as it is in your question). You can then select desired key
function getSfoLocal(callback) {
// for now I use local file for testing
document.querySelector('input').addEventListener('change', function() {
var reader = new FileReader();
reader.onload = function() {
var arrayBuffer = this.result;
var array = new Uint8Array(arrayBuffer);
// var binaryString = String.fromCharCode.apply(null, array);
if (typeof callback === 'function') callback(array);
}
reader.readAsArrayBuffer(this.files[0]);
}, false);
}
function getSfoRemote(url, callback) {
var concatArrayBuffers = function(buffer1, buffer2) {
if (!buffer1) {
return buffer2;
} else if (!buffer2) {
return buffer1;
}
var tmp = new Uint8Array(buffer1.length + buffer2.length);
tmp.set(buffer1, 0);
tmp.set(buffer2, buffer1.byteLength);
return tmp.buffer;
};
fetch(url).then(res => {
const reader = res.body.getReader();
let charsReceived = 0;
let result = new Uint8Array;
reader.read().then(function processText({
done,
value
}) {
// Result objects contain two properties:
// done - true if the stream has already given you all its data.
// value - some data. Always undefined when done is true.
if (done) {
if (typeof callback === 'function') callback(result);
return result;
}
// value for fetch streams is a Uint8Array
charsReceived += value.length;
const chunk = value;
result = concatArrayBuffers(result, chunk);
// Read some more, and call this function again
return reader.read().then(processText);
});
});
}
function getSfo(type, url, callback) {
if (type === 'local') getSfoLocal(callback);
if (type === 'remote') getSfoRemote(url, callback);
}
getSfo('local', null, (data) => {
keys = parse_sfo(data);
console.log('LOCAL =', keys);
});
function goremote() {
getSfo('remote', 'https://srv-file9.gofile.io/download/Y0gVfw/PARAM.SFO', (data) => {
keys = parse_sfo(data);
console.log('REMOTE =', keys);
});
}
div { padding: 4px; }
<!--script src="https://rawcdn.githack.com/KuromeSan/sfo.js/c7aa8209785cc5a39c4231e683f6a2d1b1e91153/sfo.js" for="release"></script-->
<script src="https://raw.githack.com/KuromeSan/sfo.js/master/sfo.js" for="develop"></script>
<div>Local version: <input type="file" /></div>
<div>Remote version: <button onclick="goremote()">Go remote</button></div>
P.S. It seems that gofile.io service that I've used for remote example is not visible sometimes. If you have permanent link to param.sfo just let me know. But now I have to visit my file, and only after that it becomes visible.
You are using some 20 years old JavaScript.
Please use fetch add TextEncoder for your own sanity.
fetch(url).then(res => res.json().then(data => {
const encoder = new TextEncoder()
const bytes = encoder.encode(data)
parse_sfo(data)
})
sfoBytes should be the actual array buffer of the sfo file. It's simpler than what you are trying, you shouldn't need to convert the request response with stringToArrayBuffer since you can get an array buffer from XMLHttpRequest. Also, the SFO file isn't a text file, it's binary, so conversion from string wouldn't work anyway.
Changing your request to get a arraybuffer response type should do it like this:
function testing(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = "arraybuffer";
request.send(null);
if (request.status === 200) {
console.log(request.response);
var response = request.response;
var sfo = parse_sfo(response);
} else {
alert('Error!');
}
}

File uploaded does not upload if the file name has parenthesis ()

I have a FileUpload control where I upload PDF files and they get saved to a folder, the file path gets saved to the database.
The problem is when I upload a file which contains parenthesis () as part of the file name, it returns undefined. This only happens if the file name has parenthesis () , if it does not have parenthesis () it uploads fine.
This is my code
var filePaths;
function UploadFile() {
var fileUpload = document.getElementById("fuPDFupload");
var regex = new RegExp("([a-zA-Z0-9\s_\\.\-:])+(.jpg|.png|.pdf)$");
if (regex.test(fileUpload.value.toLowerCase())) {
//Check whether HTML5 is supported.
if (typeof (fileUpload.files) != "undefined") {
//Initiate the FileReader object.
var reader = new FileReader();
//Read the contents of Image File.
reader.readAsDataURL(fileUpload.files[0]);
reader.onload = function (e) {
//Initiate the JavaScript Image object.
var image = new Image();
//Set the Base64 string return from FileReader as source.
image.src = e.target.result;
var fileUpload = $("#fuPDFupload").get(0);
var files = fileUpload.files;
var data = new FormData();
for (var i = 0; i < files.length; i++) {
data.append(files[i].name, files[i]);
}
$.ajax({
url: "FileUploadHandler.ashx",
type: "POST",
data: data,
contentType: false,
processData: false,
success: function (result) {
filePaths = result;
//Save to DB
UpdateSchedule();
},
error: function (err) {
}
});
return true;
};
} else {
alert("This browser does not support HTML5.");
return false;
}
} else {
return false;
}
}
FileUploadHandler Code:
public class FileUploadHandler : IHttpHandler {
public void ProcessRequest(HttpContext context)
{
if (context.Request.Files.Count > 0)
{
string filePaths = Guid.NewGuid().ToString() + ".pdf";
HttpPostedFile file = context.Request.Files[0];
string path = context.Server.MapPath("~/QfrencyInvoices/" + filePaths);
file.SaveAs(path);
context.Response.ContentType = "text/plain";
context.Response.Write(filePaths);
}
}
public bool IsReusable {
get {
return false;
}
}
}
I believe that the problem might be happening because the Regex expression is incorrect but I have not been able to fix it.
Please assist me how I can upload files that have parenthesis () as part of the file name. Thank you.
Just leave next regex new RegExp("(\.(jpg|png|pdf)$", "i");. It checks that filename has extension jpg, png or pdf. Text case does not matter so "i" was added as the second parameter.
You can learn regular expressions on https://regexone.com/

Reading Blob of a file in javascript and inserting in database

I want to read any kind of file from my js code and insert its blob to database in long blob type column. Variable in js is reading blob as string but not as blob.
So I am facing issue if there are special characters like single/double quote etc.
reading code is
function onChooseFile(event, onLoadFileHandler) {
if (typeof window.FileReader !== 'function')
throw ("The file API isn't supported on this browser.");
let input = event.target;
if (!input)
throw ("The browser does not properly implement the event object");
if (!input.files)
throw ("This browser does not support the `files` property of the file input.");
if (!input.files[0])
return undefined;
let file = input.files[0];
let fr = new FileReader();
fr.onload = onLoadFileHandler;
fr.onloadend = function(event) {
if (event.target.readyState == FileReader.DONE) { // DONE == 2
//blobData = event.target.result;
blobData = new Blob([event.target.result], { type: fileType });
console.log(blobData);
console.log(typeof(blobData));
console.log(blobData instanceof Blob)
console.log("-------------------------------------------------");
blobString = ab2str(event.target.result);
console.log(blobData);
alert("file read complete "+blobData.length);
}
};
document.getElementById('inputHeader').value = file.name;
fileName = file.name;
fileType = file.type;
fileExtension = fileName.split(".").pop();
fr.readAsBinaryString(file);
}
Writing Code is
dataservice.openDocument(document_version_id)
.done(function (reply) {
fileExtension = fileName.split(".").pop();
switch(fileExtension.toLowerCase()){
case "doc":
case "docx":
fileType = "application/msword";
break;
case "pdf":
fileType = "application/pdf";
break;
case "xls":
case "xlsx" :
fileType = "application/vnd.ms-excel";
break;
}
var blob = new Blob([reply.RECORD_DATA.LONG_BLOB], { type: fileType });
saveAs(blob, 'C:/OutputFile/hello.'+fileExtension);
deferred.resolve();
}).fail(function (error) {
alert("failure in getting document");
deferred.reject();
});
});
Please help, how to achieve this.
Thanks

Reading local server .json file with mobileFirst javascript adapter

Is there any way that I can read a .json file (located in server) from a javascript http adapter?
I tried a lot of methods described in the internet but they don't seem to work because they are made for browser javascript (I get errors like XMLHttpRequest is not defined or activeObject is not defined).
for example, I used this but it doesn't work:
function readTextFile(file)
{
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, false);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
var allText = rawFile.responseText;
return allText;
}
}
}
rawFile.send(null);
}
Is there any way that I could do this without using java?
You can read a file with Javascript as shown below.
function readFile(filename) {
var content = "";
var fileReader = new java.io.FileReader(filename);
var bufferedReader = new java.io.BufferedReader(fileReader);
var line;
while((line = bufferedReader.readLine()) != null) {
content += line;
}
bufferedReader.close();
return content;
}
function test() {
var file = 'yourfilename.json';
var fileContents;
try {
fileContents = JSON.parse(readFile(file));
} catch(ex) {
// handle error
}
return {
fileContents: fileContents
};
}
For those interested in using Java.
One thing you can do is create a Javascript adapter which will use Java code. It is pretty simple to set up.
First create a Javascript adapter.
Then create a Java class under the server/lib folder. I created the class ReadJSON.java under the package com.sample.customcode.
Inside the ReadJSON.java
public class ReadJSON {
public static String readJSON() throws IOException {
//Open File
File file = new File("file.txt");
BufferedReader reader = null;
try {
//Create the file reader
reader = new BufferedReader(new FileReader(file));
String text = null;
//read file
while ((text = reader.readLine()) != null) {}
} finally {
try {
//Close the stream
reader.close();
}
}
return "the text from file";
}
}
Inside your javascript adapter you can use Java methods like below:
function readJOSN() {
var JSONfromServer = com.sample.customcode.ReadJSON.readJSON();
return {
result: JSONfromServer
};
}
Hope this helps.

MVC Asp.net zip file download

I have some code in an MVC project that creates a zip file and sends it to the browser. Everything works when I manually enter the URL in the browser, but if I click on the link in the page to get the download, I get a file of a different size and Windows cannot open it.
So, if I manually enter something like this:
http://localhost/fms-ui/File/DownloadZipFile/?id=10&filename=DST-2015-11-14_04_04_04
I get a zip file of 167 bytes and it open fine.
If I click on the link in the page, I get a file of 180 bytes and Windows says the file is corrupted. Hun?
My one stipulation is that I cannot use an external library. Due to politics I must use the library provided with .Net Framework 4.5 (static ZipFile class).
Code:
public FileContentResult DownloadZipFile(int id, string filename)
{
/*
* 1 - get fileset info
* 2 - get temp file name
* 3 - create zip file under temp name
* 4- return file
*/
QuesterTangent.Wayside.FileServices.FileSet sInfo = new QuesterTangent.Wayside.FileServices.FileSet(id);
string path = Path.Combine(sInfo.BasePath);
string tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".zip");
ZipFile.CreateFromDirectory(path, tempPath);
byte[] fileBytes = System.IO.File.ReadAllBytes(tempPath);
//System.IO.File.Delete(tempPath); Commented so I can compare the files
filename = filename + ".zip";
var cd = new System.Net.Mime.ContentDisposition
{
FileName = filename,
Inline = false,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(fileBytes, "application/zip");
}
I've tried this with and without AppendHeader and with various contentTypes, but it doesn't seem to effect the outcome.
Here is the JavaScript that calls the controller (I inherited this code but it works for other things).
function GetFile(url) {
//spin a wheel for friendly buffering time
var buffer = $('.MiddleRightDiv').spinBuffer();
$.ajax({
url: url,
type: "POST",
cache: false,
async: true,
data: {},
success: function (response, status, xhr) {
// check for a filename
var filename = "";
var disposition = xhr.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}
var type = xhr.getResponseHeader('Content-Type');
var blob = new Blob([response], { type: type });
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
window.navigator.msSaveBlob(blob, filename);
} else {
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(blob);
if (filename) {
// use HTML5 a[download] attribute to specify filename
var a = document.createElement("a");
// safari doesn't support this yet
if (typeof a.download === 'undefined') {
window.location = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
} else {
window.location = downloadUrl;
}
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
}
},
complete: function (result) {
if (typeof $('.MiddleRightDiv').spinBuffer !== 'undefined' && $.isFunction($('.MiddleRightDiv').spinBuffer)) {
$('.MiddleRightDiv').spinBuffer("destroy");
}
}
});
Any input would be a great help. I have gone over other similar postings but non of them seems to address the core problem I am having.
Thanks,
dinsdale
jQuery.ajax cannot read bytestreams correctly (check SO for many topics about this), so we have to use old and good XMLHttpRequest. Here is your function refactored to work with blobs. Extened it with fallbacks for other browsers while saveAs(blob,filename) is the draft.
function GetFile(url) {
if (window.navigator.msSaveBlob) {
var req = new XMLHttpRequest();
req.open('GET', url);
req.responseType = 'arraybuffer';
req.onload = function (e) {
if (req.response) {
var filename = 'archive.zip';
var disposition = req.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}
var type = req.getResponseHeader('Content-Type');
var blob = new Blob([req.response], { type: type ? type : 'application/octet' });
window.navigator.msSaveBlob(blob, filename);
} else {
throw 'Empty or invalid response';
}
}
req.send();
} else {
//fallback for browsers without blob saver
throw 'Not implemented';
}
}

Categories