QUOTA_EXCEEDED_ERR in Chrome FileSystem API - javascript

In Chrome23/Mac OS 10.8.2 this fiddle logs an error, and I want to know why.
Surprisingly enough, error does not occur if I put a breakpoint on the line that says '// BREAKPOINT' and simply resume execution.
Is it possible for JS to exceed some call rate limit in Chrome? I couldn't think of a better explanation.
Full code (I am using lodash, see its documentation of _.bind and _.bindAll):
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.LocalFileSystem = window.LocalFileSystem || {PERSISTENT: window.PERSISTENT};
fs = {
initFS: function() {
window.requestFileSystem(LocalFileSystem.PERSISTENT,
1024 * 1024, this.gotFS, this.fail);
},
fail: function(source, err) {
err.source = source;
var msg = '';
switch (err.code) {
case FileError.QUOTA_EXCEEDED_ERR:
msg = 'QUOTA_EXCEEDED_ERR';
break;
case FileError.NOT_FOUND_ERR:
msg = 'NOT_FOUND_ERR';
break;
case FileError.SECURITY_ERR:
msg = 'SECURITY_ERR';
break;
case FileError.INVALID_MODIFICATION_ERR:
msg = 'INVALID_MODIFICATION_ERR';
break;
case FileError.INVALID_STATE_ERR:
msg = 'INVALID_STATE_ERR';
break;
default:
msg = 'Unknown Error';
break;
};
err.msg = msg;
console.log('err ', JSON.stringify(err));
},
failarg: function(msg) {
return _.bind(this.fail, this, msg);
},
gotFS: function(fs) {
this.fs = this.fs || fs;
this.readConfig();
this.listApps(fs.root); // BREAKPOINT
},
listApps: function(fsroot) {
this.rootReader = this.rootReader || fsroot.createReader();
this.rootReader.readEntries(this.gotRootEntries, this.fail);
},
gotRootEntries: function(entries) {
_(entries).forEach(function(entry) {
if (entry.isDirectory && this.controller) {
// TODO
}
});
},
readConfig: function() {
this.fs.root.getFile('config.json', {create:true}, this.gotConfigFileEntry, this.failarg('getFile'));
},
gotConfigFileEntry: function(entry) {
entry.file(this.gotConfigFile, this.failarg('entry.file'));
},
gotConfigFile: function(file) {
this.configFile = file;
var reader = new FileReader();
reader.onloaded = function(evt) {
if (evt.target.result) {
this.config = JSON.parse(evt.target.result);
}
};
reader.readAsText(this.configFile);
},
};
_.bindAll(fs);
$(function() {
fs.initFS();
});​

The following Fiddle, based on the original HTML 5 Rocks article (http://www.html5rocks.com/en/tutorials/file/filesystem/), demonstrates how to invoke the quota system.
http://jsfiddle.net/kim3er/h76qq/1/
window.webkitStorageInfo.requestQuota(PERSISTENT, 1024*1024, function(grantedBytes) {
//window.requestFileSystem(PERSISTENT, grantedBytes, onInitFs, errorHandler);
initFS(grantedBytes);
}, function(e) {
console.log('Error', e);
});

Related

WebRTC: Unable to to receive remote video or audio

The goal is to have a webrtc video/audio p2p connection.
I did take some examples and put them together and manage to get far enough that "most" exchange (via eventsource on NodeJS) is done, just remote stream is not received.
I found that Chrome browser had a bug in which the request is send twice (any fix for this?).
But even when I use firefox (on laptop and phone), there is just no stream received.
with no error on both sides.
This is the full script:
if (!console || !console.log) {
var console = {
log: function() {}
};
}
// Ugh, globals.
// const signaling = new SignalingChannel(); hier moet een module voor komen, als een EventServerSide en/of Websocket...
var peerc;
var source = new EventSource("events");
var selfView = document.getElementById('localvideo');
var remoteView = document.getElementById('remotevideo');
//var TextHistory = ["apple", "orange", "cherry"]; //[ ];
var audio = null;
var audioSendTrack = null;
var video = null;
var videoSendTrack = null;
var chatbox = document.getElementById("chatbox");
var constraints = {video:true, audio:true};
var configuration = {
iceServers: [{
'urls': 'stun:stun.l.google.com:19302'
}]
};
var started = false;
var pc;
$("#incomingCall").modal();
$("#incomingCall").modal("hide");
$("#incomingCall").on("hidden", function() {
document.getElementById("incomingRing").pause();
});
source.addEventListener("ping", function(e) {}, false);
source.addEventListener("userjoined", function(e) {
appendUser(e.data);
}, false);
source.addEventListener("userleft", function(e) {
removeUser(e.data);
}, false);
source.addEventListener("offer", async function(e) {
log("offer received");
if (!pc) {
log("PeerConnection ontbreekt");
warmup(false);
} else {
warmup(true);
}
try {
const message = JSON.parse(e.data);
if (message.desc) {
log("Offer: Desc");
const desc = message.desc;
// if we get an offer, we need to reply with an answer
if (desc.type == 'offer') {
log("Offer: Desc offer");
var connectionState = pc.connectionState;
log(connectionState);
await pc.setRemoteDescription(JSON.parse(desc)); // Parse nodig?
await pc.setLocalDescription(await pc.createAnswer());
var connectionState = pc.connectionState;
log(connectionState);
//signaling.send(JSON.stringify({desc: pc.localDescription}));
jQuery.post(
"offer", {
to: message.from,
from: document.getElementById("user").innerHTML,
desc: JSON.stringify(pc.localDescription)
},
function() { log("Offer sent!"); }
).error("desc", error);
} else {
log("Offer: Desc answer");
await pc.setRemoteDescription(JSON.parse(desc));
}
} else if (message.start) {
log("Offer: Start received from: " + message.from);
started = true;
voor = message.from
van = message.to
if (audio && audioSendTrack) {
log("Wacht op audio");
await audio.sender.replaceTrack(audioSendTrack);
}
if (video && videoSendTrack) {
log("Wacht op video");
await video.sender.replaceTrack(videoSendTrack);
}
log("Offer: Started....wat next???");
} else {
log("Offer: wacht op candidate");
log(message.candidate);
await pc.addIceCandidate(message.candidate);
}
} catch (err) {
console.log(err);
log("Error in Offer event: " + err);
}
}, false);
source.addEventListener("message", function(e) {
var message = JSON.parse(e.data);
text = "User: " + message.from + " - Say: " + message.text;
WriteChat(text);
}, false);
source.addEventListener("answer", function(e) {
var answer = JSON.parse(e.data);
peerc.setRemoteDescription(new RTCSessionDescription(JSON.parse(answer.answer)), function() {
console.log("Call established!");
}, error);
}, false);
function log(info) {
var d = document.getElementById("debug");
d.innerHTML += info + "\n\n";
}
function appendUser(user) {
// If user already exists, ignore it
var index = users.indexOf(user);
if (index > -1)
return;
users.push(user);
console.log("appendUser: user = " + user + ", users.length = " + users.length);
var d = document.createElement("div");
d.setAttribute("id", btoa(user));
var a = document.createElement("button");
a.setAttribute("class", "vertical-align");
a.setAttribute("onclick", "initiateCall('" + user + "');"); //Dit moet dus prive chat worden.
a.innerHTML = "<i class='icon-user icon-white'></i> " + user;
d.appendChild(a);
d.appendChild(document.createElement("br"));
document.getElementById("users").appendChild(d);
}
function removeUser(user) {
// If user already exists, ignore it
var index = users.indexOf(user);
if (index == -1)
return;
users.splice(index, 1)
var d = document.getElementById(btoa(user));
if (d) {
document.getElementById("users").removeChild(d);
}
}
function sendPrive(user) {
log("Prive message"); // + JSON.stringify(offer));
if(!user) { user = "niets!"};
jQuery.post(
"message", {
to: user,
from: document.getElementById("user").innerHTML,
text: JSON.stringify(message)
},
function() { console.log("Message sent!"); }
).error("privemsg",error);
}
function offer(data){
log("Offer to send message: " + JSON.stringify(data));
// start
// desc + type
// candidate
jQuery.post(
"offer", {data: JSON.stringify(data)},
function() { console.log("Message sent!"); }
).error("offer",error);
}
function BroadcastMessage() {
log("Broadcast Message"); // + JSON.stringify(offer)); //function uitbreiden met argumentinvoer
message = document.getElementById("text_input").value;
jQuery.post(
"message", {
to: user,
from: document.getElementById("user").innerHTML,
text: JSON.stringify(message)
},
function() { console.log("Message sent!"); }
).error("BroadcastMessage",error);
//WriteChat(msg);
}
// Dit is een interne, dit moet dus via events gaan!!
function WriteChat(text){
// kan nog user en tijd bijkomen...
chatbox.innerHTML += text + "<br>"; // deze werkt dus niet meer, canvas wil andere methode
}
// Call warmup() to warm-up ICE, DTLS, and media, but not send media yet.
async function warmup(isAnswerer) {
log("Warming up...");
pc = new RTCPeerConnection(configuration);
if (!isAnswerer) { //uitzoeken waarom deze uitgeschakelen...
audio = pc.addTransceiver('audio');
video = pc.addTransceiver('video');
}
// send any ice candidates to the other peer
pc.onicecandidate = (event) => {
log("Offer: onicecandidate...");
//signaling.send(JSON.stringify({candidate: event.candidate}));
log(event.candidate)
if(event.candidate){
jQuery.post(
"offer", {
to: voor,
from: document.getElementById("user").innerHTML,
data: event.candidate, // debugging...
candidate: event.candidate
}, // hier zijn we nu...candidate blijft leeg????
function() { log("Offer: onicecandidate sent!"); }
).error("onicecandidate",error);
} else {
log("geen candidate");
}
};
pc.onnegotiationneeded = function() {
log("negotiation nodig...");
//var connectionState = RTCPeerConnection.connectionState;
pc.createOffer().then(function(aanbod) {
var connectionState = pc.connectionState;
log(connectionState);
log(JSON.stringify(aanbod));
return pc.setLocalDescription(aanbod);
})
.then(function() {
log(JSON.stringify(pc.localDescription));
jQuery.post(
"offer", {
to: document.getElementById("user").innerHTML,
from: voor,
desc: JSON.stringify(pc.localDescription)
},
function() { log("Offer: localDescription sent!"); }
).error("onnegotiationneeded",error);
})
.catch(error);
}
log("Remote video");
// once media for the remote track arrives, show it in the remote video element
pc.ontrack = async (event) => {
log("start ontrack...");
remoteView.srcObject = event.streams[0];
remoteView.play();
selfView.play();
log("oude ontrack...");
try {
log(event.track.kind);
if (event.track.kind == 'audio') {
log("Track heeft audio");
if (isAnswerer) {
log("beantwoord audio");
audio = event.transceiver;
audio.direction = 'sendrecv';
if (started && audioSendTrack) {
await audio.sender.replaceTrack(audioSendTrack);
}
}
}
} catch (err) {
console.log(err);
log("Error in audio ontrack: " + err);
}
try {
log(event.track.kind);
if (event.track.kind == 'video') {
log("Track heeft video");
if (isAnswerer) {
log("beantwoord video");
video = event.transceiver;
video.direction = 'sendrecv';
if (started && videoSendTrack) {
await video.sender.replaceTrack(videoSendTrack);
}
}
}
} catch (err) {
console.log(err);
log("Error in video ontrack: " + err);
}
try {
// don't set srcObject again if it is already set.
if (!remoteView.srcObject) {
log("Nog geen remote video...");
remoteView.srcObject = new MediaStream();
}
log("Voeg remote video toe...");
log(event.track);
remoteView.srcObject.addTrack(event.track);
} catch (err) {
console.log(err);
log("Error in last ontrack: " + err);
}
};
log("Local video & audio");
try {
// get a local stream, show it in a self-view and add it to be sent
const stream = await navigator.mediaDevices.getUserMedia(constraints);
selfView.srcObject = stream;
audioSendTrack = stream.getAudioTracks()[0];
if (started) {
log("Started = True => audio");
log(audio)
await audio.sender.replaceTrack(audioSendTrack);
}
videoSendTrack = stream.getVideoTracks()[0];
if (started) {
log("Started = True => video");
log(video)
await video.sender.replaceTrack(videoSendTrack);
}
} catch (err) {
console.log(err);
log("Error in local video & audio: " + err);
}
log("Warmup completed");
}
function initiateCall(user) {
log("Start van video verzoek");
// Verander UI
//document.getElementById("main").style.display = "none";
//document.getElementById("call").style.display = "block";
log("Voor gebruiker: " + user);
voor = user;
log("Van gebruiker: " + document.getElementById("user").innerHTML);
van = document.getElementById("user").innerHTML;
started = true;
//offer(JSON.stringify({start: true}));
jQuery.post(
"offer", {
to: user,
from: document.getElementById("user").innerHTML,
start: true
},
function() { console.log("Offer sent!"); }
).error("initiateCall",error);
}
function endCall() {
log("Ending call");
document.getElementById("call").style.display = "none";
document.getElementById("main").style.display = "block";
document.getElementById("localvideo").mozSrcObject.stop();
document.getElementById("localvideo").mozSrcObject = null;
document.getElementById("remotevideo").mozSrcObject = null;
peerc.close();
peerc = null;
}
function error(from,e) {
if (typeof e == typeof {}) {
//alert("Oh no! " + JSON.stringify(e));
log("Oh no! " + from + " ERROR: " + JSON.stringify(e));
} else {
alert("Oh no!!!! " + from + " ERROR: " + e);
}
//endCall();
}
var users = [];
users.push(document.getElementById("user").innerHTML);
Please note that I combined examples for:
developer.mozilla.org
w3c.github.io
www.html5rocks.com
So there might be unnecessary code
If required, I can put all code in repository and share that for full view.
Additional logging shows the following errors:
DOMException: "Cannot add ICE candidate when there is no remote SDP"
InvalidModificationError: Cannot set local offer when createOffer has not been called.
You should try to use a TURN-Server. Even for usage in development. The traffic will be relayed if a direct P2P-connection can't be stablished.
Have a look at Coturn.
I can't say that this will be the solution for the current problem, but in my opinion most of the issues will be solved - and for production use, you will need it definitely.
I found the problem and solution.
First:
The STUN/TURN server was not a problem, this
urls: 'stun:stun.l.google.com:19302'
Is enough for local network development.
But I did install turnserver (ubuntu 18) which seems fine.
Second:
My problem was first in de message exchange, you need to make sure the OFFER/ANSWER go to right clients.
Last:
The negotiation needs to be stable before sending/receiving media.
I modified my code that connection and start video sending are separated.
Also this allows for just one side to send media or not.

how to append to file with cordova-plugin-file

I'm trying to append text to a file.
I have followed tutorial of Html5rocks as suggested by plugins's github page.
I've sucessfully created a file and wrote to it. But when im trying to append text, i got a write success event but no text is added. I'm only able to change characters but no characted added to the end. It's not an async issue, i'm also trying live test with chrome's js console. Im also using fileWriter.seek(fileWriter.length) before trying to write at the end. (but seek(0) to write a the beginning)
there is the module i wrote :
'use strict';
function File_mgmt(name) {
var name = name;
var myfile = '';
var next_write = '';
var that = this;
var errorHandler = function (e) {
var msg = '';
switch (e.code) {
case FileError.QUOTA_EXCEEDED_ERR:
msg = 'QUOTA_EXCEEDED_ERR';
break;
case FileError.NOT_FOUND_ERR:
msg = 'NOT_FOUND_ERR';
break;
case FileError.SECURITY_ERR:
msg = 'SECURITY_ERR';
break;
case FileError.INVALID_MODIFICATION_ERR:
msg = 'INVALID_MODIFICATION_ERR';
break;
case FileError.INVALID_STATE_ERR:
msg = 'INVALID_STATE_ERR';
break;
default:
msg = 'Unknown Error';
break;
};
console.log('Error: ' + msg);
};
var init = function() {
console.log("init");
request(gotFS);
};
var gotFS = function() {
console.log("gotfs");
window.resolveLocalFileSystemURL(cordova.file.externalDataDirectory, function(dir) {
dir.getFile(name, {create:true}, function(file) {
myfile = file;
}, errorHandler);
});
};
this.write = function (data) {
myfile.createWriter(function(fileWriter) {
fileWriter.onwriteend = function(e) {
console.log('Write completed.');
};
fileWriter.onerror = function(e) {
console.log('Write failed: ' + e.toString());
};
// Create a new Blob and write it to log.txt.
fileWriter.seek(fileWriter.length);
fileWriter.write(data);
}, errorHandler);
};
this.reopen = function() {
window.resolveLocalFileSystemURL(cordova.file.externalDataDirectory, function(dir) {
dir.getFile(name, {create:false}, function(file) {
myfile = file;
}, errorHandler);
});
};
this.getfile = function() {
return myfile;
};
this.writeTextBlob = function(data) {
this.write(new Blob([data], {type: 'text/plain'}));
};
var request = function(success){
var fail = function() {console.log("failed to initialise system")};
window.requestFileSystem(LocalFileSystem.PERSISTENT, 1024*1024, success, fail);
};
var writer = function() {
myfile.createWriter(function(fileWriter) {
fileWriter.onwriteend = function(e) {
console.log('Write completed.');
};
fileWriter.onerror = function(e) {
console.log('Write failed: ' + e.toString());
};
// Create a new Blob and write it to log.txt.
fileWriter.seek(fileWriter.length);
fileWriter.write(next_write);
}, errorHandler);
};
this.testWrite = function(data) {
next_write = data;
request(writer);
};
init();
return this;
}
I'm using it with chrome console with
var f = new File_mgmt("test");
f.writeTextBlob("test1");
f.writeTextBlob("test2");
Edit
I've tried to pass by a window.requestFileSystem() to append but it still doesnt work, I've also updated my code.
now i'm doing
var f = new File_mgmt("test");
f.testWrite("test1");
f.testWrite("test2");
It's appearing than my file actually got new data. I had to unplugged then replugged usb cable to see the new data appened to my file.
May be it's a problem with Windows. I'll look if i got the same problem on linux.

bulkTransfer "Transfer failed."

I'm not getting any kind of transfer to happen between my chrome app and a simple device just waiting for data to come in on its uart rx line. The device's interface's endpoint's type is bulk, although I've tried every transfer type available (control, bulk, isochronous, and interrupt). Examples from here. I've also tried claiming the device, but that does not seem to be applicable if using findDevices and fails as well.
I'm assuming that by finding the device, I know that it has been discovered, permissions are OK and that it has been opened OK.
I'm using a UART-to-USB adapter on a mac. I've spoken to the same hardware setup using pysusb and a python script, so I know it can be done.
var DEVICE_INFO = {"vendorId": 1027, "productId": 24577};
var searchForUsbDevice = function() {
chrome.usb.findDevices(DEVICE_INFO, onDeviceFound);
}
var onDeviceFound = function(devices) {
if (devices) {
if (0 < devices.length) {
if (1 === devices.length) {
device_ = devices[0];
console.log("Device found. And opened?");
getInterfaces();
getConfiguration();
//claimDevice();
investigateDevice();
} else {
console.log("Ensure one and ONLY ONE device is plugged in.");
}
} else {
console.log("Device could not be found");
setTimeout(searchForUsbDevice, 1000);
}
} else {
console.log("Permission denied.");
}
};
var investigateDevice = function() {
testBulkTransfer();
//testIsochronousTransfer();
//testInterruptTransfer();
//testControlTransfer();
setTimeout(investigateDevice, 1000);
};
var testBulkTransfer = function() {
var transferInfo = {
"direction": "out",
"endpoint": 1,
"data": new Uint8Array([32, 2, 1, 2]).buffer
};
chrome.usb.bulkTransfer(device_, transferInfo, function(info) {
if (chrome.runtime.lastError) {
console.log("info: " + JSON.stringify(info));
console.log("runtime error: " + JSON.stringify(chrome.runtime.lastError.message));
return;
}
console.log("transfer result: " + ((0 === info.resultCode) ? "succeeded" : "failed"));
});
};
var getConfiguration = function() {
chrome.usb.getConfiguration(device_, function(config) {
if (chrome.runtime.lastError) {
console.log("runtime error: " + JSON.stringify(chrome.runtime.lastError.message));
return;
}
console.log("config: ");
console.log(config);
});
};
var getInterfaces = function() {
chrome.usb.listInterfaces(device_, function(descriptors) {
if (chrome.runtime.lastError) {
console.log("runtime error: " + JSON.stringify(chrome.runtime.lastError.message));
return;
}
console.log("descriptors: ");
console.log(descriptors);
});
};
The appropriate API for that UART-to-USB adapter is chrome.serial, NOT chrome.usb.
https://developer.chrome.com/apps/app_serial

Merging multiple parts of a file in Cordova

Within my Cordova app, I am downloading arbitrary files like images or video files. This is done with the Cordova file-transfer plugin and the "Range" Header, because I need to download the files in parts.
My Problem is, that I want to merge back the several small "Byte"-Files back together into the original file they once where to use that file. Every time I'm trying to read the resulting parts as binaryString via the FileReader and write them together in a new file, that file ends up a lot larger than the parts of the original file altogther and the resulting file is unusable.
Any help is appreciated.
Here is my code until now (long and ugly):
document.addEventListener('deviceready', deviceready, false);
var App;
var finishedFileUrl = "";
var async = {
sequence: function(items, callback) {
var def = $.Deferred(),
deferrers = [$.Deferred()];
for(var i = 0; i < items.length; i++) {
(function (n) {
deferrers[n + 1] = $.Deferred();
deferrers[n].always(function() {
callback(items[n], deferrers[n + 1]);
});
})(i);
}
deferrers[items.length].always(function() {
def.resolve();
});
deferrers[0].resolve();
return def.promise();
}
}
var aSmallImageArray = [
'' // Put URL to JPG accessible with Range Header Request here
];
var aByteSizeImageArray = [];
function formatDownloadArray(fileSize) {
for(var j = 1000; j <= fileSize; j += 1000) {
aByteSizeImageArray.push(j);
}
aByteSizeImageArray.push(j);
}
function deviceready() {
console.log('dv ready');
function registerHandlers() {
App = new DownloadApp();
formatDownloadArray(XXXXX); // XXXXX should be size of JPG in bytes
document.getElementById("startDl").onclick = function() {
var that = this;
console.log("load button clicked");
var folderName = "testimagefolder";
// sequence call
async.sequence(aByteSizeImageArray, function(currentBytes, iter) {
var filePath = aSmallImageArray[0];
var fileName = aSmallImageArray[0].substr(52,99) + currentBytes;
console.log(filePath);
console.log(fileName);
console.log("Starting with: " + fileName);
var uri = encodeURI(filePath);
var folderName = "testimagefolder";
document.getElementById("statusPlace").innerHTML = "<br/>Loading: " + uri;
App.load(currentBytes, uri, folderName, fileName,
function progress (percentage) {
document.getElementById("statusPlace").innerHTML = "<br/>" + percentage + "%";
},
function success (entry) {
console.log("Entry: " + entry);
document.getElementById("statusPlace").innerHTML = "<br/>Image saved to: " + App.filedir;
console.log("DownloadApp.filedir: " + App.filedir);
iter.resolve();
},
function error () {
document.getElementById("statusPlace").innerHTML = "<br/>Failed load image: " + uri;
iter.resolve();
}
);
}).then(function afterAsync () {
console.log("ASYNC DONE");
var ohNoItFailed = function ohNoItFailed (exeperro) {
console.log(exeperro);
}
// now we merge the fileparts into one file to show it
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (FileSystem) {
FileSystem.root.getDirectory(folderName, {create: true, exclusive: false}, function itSuccessed (Directory) {
Directory.getFile(aSmallImageArray[0].substr(52,99), {create: true, exclusive: false}, function itSuccessedAgain (fileEntry) {
finishedFileUrl = fileEntry.toURL();
var directoryReader = Directory.createReader();
var allFiles = directoryReader.readEntries(function succesReadDir (fileEntries) {
async.sequence(fileEntries, function(currentFile, iterThis) {
currentFile.file(function (theActualFile) {
var myFileReader = new FileReader();
myFileReader.onload = function (content) {
console.log('FileReader onload event fired!');
console.log('File Content should be: ' + content.target.result);
fileEntry.createWriter(
function mergeImage (writer) {
writer.onwrite = function (evnt) {
console.log("Writing successful!");
iterThis.resolve();
}
writer.seek(writer.length);
writer.write(content.target.result);
}, ohNoItFailed);
};
myFileReader.readAsBinaryString(theActualFile);
}, ohNoItFailed);
}).then(function afterAsyncTwo () {
console.log("NOW THE IMAGE SHOULD BE TAKEN FROM THIS PATH: " + finishedFileUrl);
//window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (FileSystem) {
//FileSystem.root.getDirectory(folderName, {create: true, exclusive: false}, function itSuccessed (Directory) {
//Directory.getFile(aSmallImageArray[0].substr(52,99), {create: true, exclusive: false}, function itSuccessedAgain (fileEntry) {
//fileEntry.createWriter(
document.getElementById("image_here").src = finishedFileUrl;
});
}, ohNoItFailed);
}, ohNoItFailed);
}, ohNoItFailed);
}, ohNoItFailed);
});
};
}
registerHandlers();
}
var DownloadApp = function() {}
DownloadApp.prototype = {
filedir: "",
load: function(currentBytes, uri, folderName, fileName, progress, success, fail) {
var that = this;
that.progress = progress;
that.success = success;
that.fail = fail;
filePath = "";
that.getFilesystem(
function(fileSystem) {
console.log("GotFS");
that.getFolder(fileSystem, folderName, function(folder) {
filePath = folder.toURL() + fileName;
console.log("FILEPATH: " + filePath);
console.log("URI: " + uri);
that.transferFile(currentBytes, uri, filePath, progress, success, fail);
}, function(error) {
console.log("Failed to get folder: " + error.code);
typeof that.fail === 'function' && that.fail(error);
});
},
function(error) {
console.log("Failed to get filesystem: " + error.code);
typeof that.fail === 'function' && that.fail(error);
}
);
},
getFilesystem: function (success, fail) {
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, success, fail);
},
getFolder: function (fileSystem, folderName, success, fail) {
fileSystem.root.getDirectory(folderName, {create: true, exclusive: false}, success, fail)
},
transferFile: function (currentBytes, uri, filePath, progress, success, fail) {
var that = this;
that.progress = progress;
that.success = success;
that.fail = fail;
console.log("here we go");
console.log("filePath before Request: " + filePath);
var previousBytes = currentBytes - 1000;
var transfer = new FileTransfer();
transfer.onprogress = function(progressEvent) {
if (progressEvent.lengthComputable) {
var perc = Math.floor(progressEvent.loaded / progressEvent.total * 100);
typeof that.progress === 'function' && that.progress(perc); // progression on scale 0..100 (percentage) as number
} else {
}
};
transfer.download(
uri,
filePath,
function success (entry) {
console.log("File saved to: " + entry.toURL());
typeof that.success === 'function' && that.success(entry);
},
function errorProblem(error) {
console.log("An error has occurred: Code = " + error.code);
console.log("download error source " + error.source);
console.log("download error target " + error.target);
console.log("download error code " + error.code);
typeof that.fail === 'function' && that.fail(error);
},
true,
{
headers: {
"Range": "bytes=" + previousBytes + "-" + currentBytes
}
}
);
}
}
async code by stackoverflow-user: Paul Facklam
-> Thanks a lot!
you can build a blob from other blobs, like the ones you use FileReader on now. (File()s are Blobs)
// put three blobs into a fourth:
var b=new Blob([new Blob(["hello"]), new Blob([" "]), new Blob(["world"])]);
// verify the blob has the data we expect:
var fr=new FileReader();
fr.onload=function(){alert(this.result);};
fr.readAsBinaryString(b); // shows: "hello world"
the binaryString flavor is used here to show how these low-order strings stack up, but the actual new blob instance should have all the orig (arbitrary) bytes from the original blobs, even if they aren't composed of simple strings...
Using readAsArrayBuffer() instead of readAsBinaryString() did the trick!
So instead of:
myFileReader.readAsBinaryString(theActualFile);
I did:
myFileReader.readAsBinaryArray(theActualFile);
And the resulting image file is usable.

chrome extension download files

I'm writing a js extension for chrome that should download multiple created files.
the problem is that chrome auto opens the file in the current tab at the following address:
filesystem:https://stackoverflow.com//temporary/myfile.ini
and second if I cycle on an array made this way
fileini = [ ["filename",file-content], [], ... ] it just print the last one
and if I try to cycle on it using a setTimeout I get an error from the console
below I post the code
function createDataFile(filename, content) {
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(window.TEMPORARY, 1024 * 1024 * 20, function(fs) {
fs.root.getFile(filename, {
create : true
}, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
var blob = new Blob(content);
console.log("5");
fileWriter.addEventListener("writeend", function() {
// navigate to file, will download
location.href = fileEntry.toURL();
}, false);
fileWriter.write(blob);
}, function() {
});
}, function() {
});
}, errorHandler);
}
function errorHandler(e) {
var msg = '';
switch (e.code) {
case FileError.QUOTA_EXCEEDED_ERR:
msg = 'QUOTA_EXCEEDED_ERR';
break;
case FileError.NOT_FOUND_ERR:
msg = 'NOT_FOUND_ERR';
break;
case FileError.SECURITY_ERR:
msg = 'SECURITY_ERR';
break;
case FileError.INVALID_MODIFICATION_ERR:
msg = 'INVALID_MODIFICATION_ERR';
break;
case FileError.INVALID_STATE_ERR:
msg = 'INVALID_STATE_ERR';
break;
default:
msg = 'Unknown Error';
break;
};
console.log('Error: ' + msg);
}
createFileCycle();
function prnt(x) {
var y;
if (fileini[x] !== undefined) {
createDataFile(fileini[x][0], objToArray(fileini[x][1]));
y = x - 1;
console.log("printed file" + x);
} else {
y = x - 1;
}
if (x > 0)
return setTimeout(function() {
console.log("going to print file " + y);
prnt(y);
}, 500);
else
return 0;
}
prnt(fileini.length - 1);
}
function createFileCycle() creates fileini array as explained above
I hope someone could help me.
btw months ago on an old notebook running ubuntu 32bit I had it working, now on windows 7 it doesn't work and I cannot get around the problem.

Categories

Resources