I am not able to show the FileSystem tab in my dev tool
I am using this code to add content to a file but i am not able to view the file in my dev tools
also i tried the following but didn't work: filesystem:https://localhost:3000/persistent/log.txt
export class ErrorLoging {
static init = () => {
var mself = this;
navigator.webkitPersistentStorage.requestQuota(1024*1024, function() {
window.webkitRequestFileSystem(window.PERSISTENT , 1024*1024, mself.onFs);
})
}
static onFs = (fs) => {
fs.root.getFile('/log.txt', { create: true }, (fileEntry) => {
// Create a FileWriter object for our FileEntry.
fileEntry.createWriter((fileWriter) => {
fileWriter.onwrite = (e) => {
console.log('Write completed.');
};
fileWriter.onerror = (e) => {
console.log('Write failed: ' + e.toString());
};
var blob = new Blob(["Lorem Ipsum"], {type: "text/plain"});
fileWriter.write(blob);
});
});
}
}
Related
I'm working on node js app that is creating pdf by user id (using pdfkit), fills with user data and then uploads to Google Drive using Google Drive API. Client is getting back URL of this file. My problem is that when I upload it once, it works perfectly. But when I'm trying to do it again, the file uploads but it's empty. If I restart server it works again.
Pdf creation is also fine on the second attempt, the only problem is second create/upload. I have tried making the name of the file dynamic but that did not help. Only server restart works. Thank you.
Function for creating pdf
const createPdf = async (req, res, missions) => {
try {
const { _id } = req.user;
const pdfPath = path.join('data', 'pdf', _id + '.pdf');
let doc = new PDFDocument({ margin: 50 });
doc.pipe(fs.createWriteStream(pdfPath));
generateInnerPdf(doc, missions);
doc.end();
return { success: true };
} catch (err) {
return { success: false };
}
};
Function for upload on google drive and retrieve url
exports.uploads = (_id) => {
return new Promise((resolve) => {
const auth = new google.auth.JWT(
credentials.client_email,
null,
credentials.private_key,
scopes
);
const drive = google.drive({ version: 'v3', auth });
var folderId = 'xxxxxxxxxxx';
const pdfPath = path.join('data', 'pdf', _id + '.pdf');
var fileMetadata = {
name: `${_id}.pdf`,
parents: [folderId],
};
var media = {
mimeType: 'application/pdf',
body: fs.createReadStream(pdfPath),
};
drive.files.create(
{
resource: fileMetadata,
media: media,
fields: 'id',
},
(error, result) => {
resolve({
fileUrl: `https://drive.google.com/file/d/${result.data.id}/view?usp=sharing`,
});
}
);
});
};
My pdf controller
exports.create = async (req, res) => {
try {
const { missions } = await getMissions(req.user._id);
const { success } = await createPdf(req, res, missions);
if (success) {
googleApi.uploads(req.user._id).then((result) => {
res.status(200).send(result);
});
} else {
res.status(422).send(err);
}
} catch (err) {
console.log(err);
res.status(422).send(err.message);
}
};
EDIT: Should be a problem when I'm resolving promise again?
Fixed when setting timeout
if (success) {
setTimeout(function () {
googleApi.uploads(req.user._id).then((result) => {
res.status(200).send(result);
});
}, 500);
I have a cordova - ionic application.
I want to download a file from webservice and the file may be any type(JPG,PDG,DOCX etc). I cannot download the file from direct URL. So the app is taking byte array of the file from Webservice.
Anybody know how to download the file in Mobile from the Byte Array. Please help me.
you can use the
cordova-plugin-file and the
cordova-plugin-file-opener2 plugin.
https://github.com/apache/cordova-plugin-file
https://github.com/pwlin/cordova-plugin-file-opener2
in function with the webservice your code should look like that:
var bytes = new Uint8Array(data.d);
app.writePDFToFile(fileName.split(fileName.split, bytes);
and here is teh function forcing the download:
writePDFToFile: function (fileName, data) {
try {
window.resolveLocalFileSystemURL(cordova.file.externalApplicationStorageDirectory, function (directoryEntry) {
directoryEntry.getFile(fileName, { create: true }, function (fileEntry) {
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function (e) {
//window.open(cordova.file.externalApplicationStorageDirectory + fileName, '_system', 'location=yes');
cordova.plugins.fileOpener2.open(cordova.file.externalApplicationStorageDirectory + fileName, 'application/pdf',
{
error: function (e) {
console.log('Error status: ' + e.status + ' - Error message: ' + e.message);
},
success: function () {
console.log('file opened successfully');
}
}
);
};
fileWriter.onerror = function (e) {
alert(e);
};
var blob = new Blob([data], { type: 'application/pdf' });
fileWriter.write(blob);
}, function onerror(e) {
alert(e);
});
}, function onerror(e) {
alert(e);
});
}, function onerror(e) {
alert(e);
});
} catch (e) {
alert(e);
}
},
Hope this will help!
I want to upload a video to YouTube from my phone device storage. However when I upload the file it comes through as blank. When I use the same upload code but with a web file, it works. Wondering where I am going wrong!
Method one
everything uploads correctly and the video plays on YouTube.
loadWebFile('assets/intro.mpg');
function loadWebFile(url) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.onload = function (e) {
uploadFile(xhr.response); // type: Blob
};
xhr.onerror = function (e) {
console.log('loadWebFile.onerror', e);
};
xhr.send();
};
Method two
The video title and description appears on YouTube, but the video is blank. I'm definitely passing through a valid file.
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
if (window.webkitStorageInfo) {
window.webkitStorageInfo.requestQuota(access, 1024 * 1024, function (bytes) {
if (window.requestFileSystem) {
window.requestFileSystem(access, bytes, function (filesystem) {
loadFile('/Movies/intro.mpg');
}, me.onError);
} else {
window.alert('requestFileSystem not supported');
}
}, me.onError);
} else {
window.alert('webkitStorageInfo not supported');
}
// this sends an empty video to YouTube
function loadFile(path) {
filesystem.root.getFile(path, null, function (fileEntry) {
fileEntry.file(function (file) {
uploadFile(file); // type: File
});
}, function (e) {
console.log('loadFile.error', e);
});
}
Both methods share the same upload function:
// uploads using the YouTube script
// https://github.com/youtube/api-samples/blob/master/javascript/cors_upload.js
function uploadFile(file) {
var metadata = {
snippet: {
title: 'Video title',
description: 'Video description',
tags: 'Video tags',
categoryId: 22
},
status: {
privacyStatus: 'unlisted'
}
};
var uploader = new MediaUploader({
baseUrl: 'https://www.googleapis.com/upload/youtube/v3/videos',
file: file,
token: accessToken,
metadata: metadata,
params: {
part: Object.keys(metadata).join(',')
},
onError: function (e) {
console.log('onError', JSON.parse(e));
},
onProgress: function (e) {
console.log('onProgress', e);
},
onComplete: function (e) {
console.log('onComplete', JSON.parse(e));
}
});
uploader.upload();
};
I've have an example project with some of the code (minus the upload script) here:
https://github.com/kmturley/cordova-files
Here another working solution. I tested right now and it does work. You need standard cordova-plugin-file
function uploadFileToServer (fileUri, fileName, remoteUrl, callback) {
window.resolveLocalFileSystemURL(fileUri, function (fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader()
reader.onloadend = function () {
var blob = new Blob([new Uint8Array(this.result)], { type: 'application/octet-stream' })
var fd = new FormData()
fd.append('file', blob, fileName)
var xhr = new XMLHttpRequest()
xhr.open('POST', remoteUrl, true)
xhr.onload = function () {
if (xhr.status === 200) {
if (typeof callback === 'function') { callback() }
} else {
if (typeof callback === 'function') { callback(xhr.status) }
}
}
xhr.onerror = function (err) {
if (typeof callback === 'function') { callback(err) }
}
xhr.send(fd)
}
reader.readAsArrayBuffer(file)
}, function (err) {
if (typeof callback === 'function') { callback(err) }
})
})
}
You call it:
uploadFileToServer('file:///storage/emulated/0/Android/data/myfile.jpg',
'myfile.jpg',
'https://example.com/upload_url',
(err) => {
if (err) {
console.error('Error uploading file', err)
} else {
console.log('Upload done it with success')
}
})
The oficial file-transfer plugin is deprecated and when I'm writing this, its test script fails.
This made me use a pure javascript approach and it does work
function uploadFile (localPath, fileName, remoteUrl, callback) {
// loads local file with http GET request
var xhrLocal = new XMLHttpRequest()
xhrLocal.open('get', localPath)
xhrLocal.responseType = 'blob'
xhrLocal.onerror = () => {
callback(Error('An error ocurred getting localpath on' + localPath))
}
xhrLocal.onload = () => {
// when data is loaded creates a file reader to read data
var fr = new FileReader()
fr.onload = function (e) {
// fetch the data and accept the blob
console.log(e)
fetch(e.target.result)
.then(res => res.blob())
.then((res) => {
// now creates another http post request to upload the file
var formData = new FormData()
formData.append('imagefile', res, fileName)
// post form data
const xhrRemote = new XMLHttpRequest()
xhrRemote.responseType = 'json'
// log response
xhrRemote.onerror = () => {
callback(Error('An error ocurred uploading the file to ' + remoteUrl))
}
xhrRemote.onload = () => {
if (typeof callback === 'function') {
callback(null, 'File uploaded successful, ' + xhrRemote.response)
}
}
// create and send the reqeust
xhrRemote.open('POST', remoteUrl)
xhrRemote.send(formData)
})
}
fr.readAsDataURL(xhrLocal.response) // async call
}
xhrLocal.send()
}
Now just call it something like this
uploadFile('file:///storage/emulated/0/Android/data/myfile.jpg',
'myfile.jpg',
'https://example.com/upload_url',
(err, res) => {
if (err) {
console.error(err)
} else {
console.log(res)
}
})
So to upload files I realised for:
web files use a CORS upload:
https://github.com/youtube/api-samples/blob/master/javascript/cors_upload.js
local device files us the cordova file transfer plugin:
https://github.com/apache/cordova-plugin-file-transfer
The code i'm now using for local files which uploads the file and sets correct metadata:
function uploadVideo(fileURL) {
var options = new FileUploadOptions();
options.fileKey = 'file';
options.fileName = fileURL.substr(fileURL.lastIndexOf('/') + 1);
options.mimeType = 'video/mpg';
options.chunkedMode = false;
options.headers = {
Authorization: 'Bearer ' + accessToken
};
options.params = {
"": {
snippet: {
title: 'Video title',
description: 'Video description',
tags: 'Video tags',
categoryId: 22
},
status: {
privacyStatus: 'unlisted'
}
}
};
var ft = new FileTransfer();
ft.upload(fileURL, 'https://www.googleapis.com/upload/youtube/v3/videos?part=snippet,status', function (data) {
console.log('upload success', data);
}, function (e) {
console.log('upload error', e);
}, options, true);
ft.onprogress = function (progressEvent) {
console.log('onprogress: ' + ((progressEvent.loaded / progressEvent.total) * 100) + '%');
};
}
And I also had to modify the plugin to allow the metadata to be passed through to YouTube using a single request:
FileTransfer.java
lines 374 - 376
beforeData.append("Content-Disposition: form-data; name=\"").append(key.toString()).append("\";");
beforeData.append(" filename=\"").append("file.json").append('"').append(LINE_END);
beforeData.append("Content-Type: ").append("application/json").append(LINE_END).append(LINE_END);
If you do modify the plugin, remember cordova caches this code. I use this command to force it to update the plugin:
cordova platform remove android; cordova platform add android;
I hvae used file system of javascript, and what i noticed is that the file system creates the file after the read is been performed, but physically call to readFile is after the call to writeFile.
readFile
var readFile = function () {
console.log("readfile" + new Date());
var that = this;
var result = "";
var successCallback = function (fs) {
console.log("Inside readFile()");
fs.root.getFile('rosters.txt', {create: false, exclusive: false},
function (fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function(e) {
console.log(this.result);
result = this.result;
that.showRosters(this.result);
}; //onloadend() ENDS HERE
reader.readAsText(file);
}, //fileEntry success callback ENDS HERE
function () { console.log("Error occurred during reading file");
result = "Error"; } //error callback for fileEntry.file
); //fileEntry.file ENDS HERE
}, //fs.roor.getFile success callback ENDS HERE
function () { console.log("File Not Found"); } ); //error callback fs.root
}
var errorCallback = function (e) {
console.log(e.toString());
}
this.EMarshal.reqFs.call(window,this.EMarshal.persistent, 5*1024*1024 /*5MB*/, successCallback, errorCallback);
return result
}
writeFile
var writefile = function (rosters) {
console.log("writeFile" + new Date());
var that = this;
console.log("Rosters" + rosters);
var successCallback = function (fs) {
console.log('Opened file system: ' + fs.name);
fs.root.getFile('rosters.txt', {create: true, exclusive: false},
function(fileEntry) {
console.log("File Created");
fileEntry.createWriter( function(writer) {
that.gotFileWriter(writer,rosters);
console.log("write");
}
,function() { console.log("Failed");
this.EMarshal.fail() }
);
},
function (e) {
console.log(e.toString());
} );
}
var errorCallback = function (e) {
console.log(e.toString);
};
console.log('Error: ' + msg);
}
this.EMarshal.reqFs.call(window,this.EMarshal.persistent, 5*1024*1024 /*5MB*/, successCallback, errorCallback);
}
for gotFileWriter
var gotFileWriter = function (writer,roster) {
writer.seek(writer.length);
writer.truncate(0);
roster = "tripid:" + this.tripid + roster;
writer.write(roster);
}
I tried to get the time, then also readFile is running before writeFile.
Is javascript is running 2 threads here ?
If anybody can explain why this happening it will be helpfull.
Try to check for the name property in the js-module. I have this problem while using the same plugin, it should me same as the Plugin name.
If it doesn't work switch to other one PhoneGap-SMS Plugin. This will be useful.
If you will read this document about the plugins in cordova you will get the idea, how these plugins are built. Cordova Plugin Documentation
I'm trying to delete a directory and it's contents with PhoneGap on Android using:
deleteDirectory = function deleteDirectory(uri) {
uri = uri.substring(0, uri.lastIndexOf('/'));
return $.Deferred(function (def) {
fileSystem.root.getDirectory(uri, {
create: false
}, function (directory) {
directory.removeRecursively();
def.resolve();
}, function (error) {
resolveError("Error deleting directory: ", error, def);
});
}).promise();
}
with the following error: File No Modification Allowed Error
I've confirmed this permission is set:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Where else should I be looking?
I have done it with this approach:
function ClearDirectory() {
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, onFileSystemSuccess, fail);
function fail(evt) {
alert("FILE SYSTEM FAILURE" + evt.target.error.code);
}
function onFileSystemSuccess(fileSystem) {
fileSystem.root.getDirectory(
"yours/dir/ect/ory",
{create : true, exclusive : false},
function(entry) {
entry.removeRecursively(function() {
console.log("Remove Recursively Succeeded");
}, fail);
}, fail);
}
}
From this answer:
I'd suggest using resolveLocalFileSystemURL if you want to access
locations under cordova.file.* (eg cordova.file.dataDirectory), which
is most of the time (if not always), and use requestFileSystem if you
need to have access to the root of the filesystem.
This also saves some lines of code and is more readable:
deleteFolder(fileName: string) {
const uri = `${cordova.file.dataDirectory}${fileName}`;
window.resolveLocalFileSystemURL(uri, (dirEntry: DirectoryEntry) => {
dirEntry.removeRecursively(
() => console.log('successfully deleted the folder and its content'),
e => console.error('there was an error deleting the directory', e.toString())
)
});
}
And here an awaitable version:
deleteFolder(fileName: string): Promise<void> {
const promise = new Promise<void>((resolve, reject) => {
const uri = `${cordova.file.dataDirectory}${fileName}`;
window.resolveLocalFileSystemURL(uri, (dirEntry: DirectoryEntry) => {
dirEntry.removeRecursively(() => resolve(), e => reject(e));
}, e => reject(e));
});
return promise;
}