I am currently loading dropped files by doing:
var files = e.dataTransfer.items;
for (var i = 0; i < files.length; i++) {
var file = files[i]; //typeof is 'DataTransferItem'
var url = URL.createObjectURL(file);
}
This gets me the object url, which I can then put into a music player. However, when iterating over an inputted folder:
var reader = entry.createReader();
reader.readEntries(function (res) {
res.forEach(function (entry) {
console.log('The entry:', entry);
console.log('The url:', JSON.stringify(entry.toURL()));
});
});
I get files of type FileEntry. According to this I shall be able to do file.toURL() and use that instead of an object url. This does return me an empty string. this seems to be there for a reason, but I have no idea how to fix this. I see something about a blob URL but I have no idea how that would work.
Example
Try to drag files and folders to the output screen and see it yourself
How I fixed it:
from an entry with typeof FileEntry, we can just do .file(callback), where the first parameter in the callback is of type File, which we can then just create an objectURL from:
var reader = entry.createReader();
reader.readEntries(function (res) {
res.forEach(function (entry) {
entry.file(function(file){ //this does the trick
var obj = URL.createObjectURL(file);
}
});
});
Many thanks to dandavis who provided me his javascript code and the approximate line so I could go look for it myself ;)
Related
I am working on a copy and paste feature for my website, so here is my problem. When i copy an image directly from a webpage it works as it should (the first if statement on the code), but if i am trying to copy a image from my own computer a i get a local path (like the one in the else statement)
$scope.pasteImage = function(eventPaste)
{
$scope.uploading = true;
var promises = [];
var items = (eventPaste.clipboardData || eventPaste.originalEvent.clipboardData).items;
for (var i = 0; i < items.length; i++)
{
var blob = null;
if (eventPaste.originalEvent.clipboardData.items[i].type.indexOf("image") == 0 || eventPaste.originalEvent.clipboardData.items[i] == 0)
{
blob = eventPaste.originalEvent.clipboardData.items[i].getAsFile();
}
else
{
var file = new File("file:///home/oem/testabc/vembly/source/server/images/pregnant.png")
console.log(file)
}
}
console.log(eventPaste)
console.log(blob)
var files = [blob];
uploadService.uploadMultiple(files)
}
so, my question is if its possible to transform that file (else statment) into a blob so i can use it in the uploadMultiple(files) funtction that i have.
No.
It would be a huge security problem if any website could use JavaScript to read data from any file path on your system it happened to guess existed.
I have a situation where I am converting blobURL to base64 dataURLs, but I want to do this only if url is a blobURL.
So is there any way to check whether it is valid blob url?
my blob url - blob:http://192.168.0.136/85017e84-0f2d-4791-b563-240794abdcbf
You are facing an x-y problem.
You absolutely don't need to check if your blobURI is a valid one, because you absolutely don't need to use the blobURI in order to create a base64 version of the Blob it's pointing to.
The only way to do it is to fetch the Blob and this means creating a copy of its data in memory for no-good.
What you need is a way to retrieve this Blob.
There is unfortunately no official way to do so with the web APIs, but it's not that hard to make it ourselves:
We simply have to overwrite the default URL.createObjectURL method in order to map the passed Blob in a dictionnary using the blobURI as key:
(() => {
// overrides URL methods to be able to retrieve the original blobs later on
const old_create = URL.createObjectURL;
const old_revoke = URL.revokeObjectURL;
Object.defineProperty(URL, 'createObjectURL', {
get: () => storeAndCreate
});
Object.defineProperty(URL, 'revokeObjectURL', {
get: () => forgetAndRevoke
});
Object.defineProperty(URL, 'getBlobFromObjectURL', {
get: () => getBlob
});
const dict = {};
function storeAndCreate(blob) {
var url = old_create(blob); // let it throw if it has to
dict[url] = blob;
return url
}
function forgetAndRevoke(url) {
old_revoke(url);
// some checks just because it's what the question titel asks for, and well to avoid deleting bad things
try {
if(new URL(url).protocol === 'blob:')
delete dict[url];
}catch(e){} // avoided deleting some bad thing ;)
}
function getBlob(url) {
return dict[url];
}
})();
// a few example uses
const blob = new Blob(['foo bar']);
// first normal use everyhting is alive
const url = URL.createObjectURL(blob);
const retrieved = URL.getBlobFromObjectURL(url);
console.log('retrieved: ', retrieved);
console.log('is same object: ', retrieved === blob);
// a revoked URL, of no use anymore
const revoked = URL.createObjectURL(blob);
URL.revokeObjectURL(revoked);
console.log('revoked: ', URL.getBlobFromObjectURL(revoked));
// an https:// URL
console.log('https: ', URL.getBlobFromObjectURL(location.href));
PS: for the ones concerned about the case a Blob might be closed (e.g user provided file has been deleted from disk) then simply listen for the onerror event of the FileReader you'd use in next step.
you could do something like
var url = 'blob:http://192.168.0.136/85017e84-0f2d-4791-b563-240794abdcbf';
if(url.search('blob:') == -1){
//do something
}
you may also use reg-expression based check with url.match('url expression')
for several days now I'm learning html, CSS and now javascript. What I need is a way to get the informations of an pdf document into my html webpage.
I tried several things now and couldnt find the correct answer or informations I need. So here come an use case:
get an .pdf document into a folder
get the information of all .pdf documents of the target folder (with the exact same formatting)
convert those information into html context
get this html context to show on the webpage (images and text)
1 is trivial, I can just drag and drop my documents
2 I'm thinking about something like an array, which then calls the folder to get data into it.
For this I found:
'use strict';
function getFiles(dir) {
fileList = [];
var files = fs.readdirSync(dir);
for (var i in files) {
if (!files.hasOwnProperty(i)) continue;
var name = dir + '/' + files[i];
if (!fs.statSync(name).isDirectory()) {
fileList.push(name);
}
}
return fileList;
}
console.log(getFiles('pathtodirectory'));
Here I'm always getting a reference error, no matter what the path, well I can use only a local path on my pc for now. I'm not 100% sure what everything does, but I think I got it good so far. This function just gets me a list of the documents to work with.
3 That's even more tricky for me now, but I think if I get the data to work with, I may be able to work something out.
4 I think I can do it with a little research
I am happy for any tips or solutions, as I said I'm quite new to all of this :)
regards,
Pascal
'use strict';
function getFiles(dir) {
fileList = []; // <- This becomes a global variable
Should be:
'use strict';
function getFiles(dir) {
var fileList = []; // <- Now it's local to this scope
Because creating implicit global variables are not allowed in strict mode.
Also the getDirSync return an array, so you should treat it as such:
function getFiles(dir) {
fileList = [];
var files = fs.readdirSync(dir);
for (var i = 0; i < files.length; i++) {
var name = dir + '/' + files[i];
if (!fs.statSync(name).isDirectory()) {
fileList.push(name);
}
}
return fileList;
}
Or with .reduce:
function getFiles(dir) {
return fs.readdirSync(dir).reduce(function(arr, file) {
var name = dir + '/' + file;
if (!fs.statSync(name).isDirectory()) {
arr.push(name);
}
return arr;
}, []);
}
I'm trying to insert an image into a pdf I'm creating server-side with PDFkit. I'm using cfs:dropbox to store my files. Before when I was using cvs:filesystem, it was easy to add the images to my pdf's cause they were right there. Now that they're stored remotely, I'm not sure how to add them, since PDFkit does not support adding images with just the url. It will, however, accept a buffer. How can I get a buffer from my CollectionFS files?
So far I have something like this:
var portrait = Portraits.findOne('vS2yFy4gxXdjTtz5d');
readStream = portrait.createReadStream('portraits');
I tried getting the buffer two ways so far:
First using dataMan, but the last command never comes back:
var dataMan = new DataMan.ReadStream(readStream, portrait.type());
var buffer = Meteor.wrapAsync(Function.prototype.bind(dataMan.getBuffer, dataMan))();
Second buffering the stream manually:
var buffer = new Buffer(0);
readStream.on('readable', function() {
buffer = Buffer.concat([buffer, readStream.read()]);
});
readStream.on('end', function() {
console.log(buffer.toString('base64'));
});
That never seems to come back either. I double-checked my doc to make sure it was there and it has a valid url and the image appears when I put the url in my browser. Am I missing something?
I had to do something similar and since there's no answer to this question, here is how I do it:
// take a cfs file and return a base64 string
var getBase64Data = function(file, callback) {
// callback has the form function (err, res) {}
var readStream = file.createReadStream();
var buffer = [];
readStream.on('data', function(chunk) {
buffer.push(chunk);
});
readStream.on('error', function(err) {
callback(err, null);
});
readStream.on('end', function() {
callback(null, buffer.concat()[0].toString('base64'));
});
};
// wrap it to make it sync
var getBase64DataSync = Meteor.wrapAsync(getBase64Data);
// get a cfs file
var file = Files.findOne();
// get the base64 string
var base64str = getBase64DataSync(file);
// get the buffer from the string
var buffer = new Buffer(base64str, 'base64')
Hope it'll help!
Am working on an offline application using HTML5 and jquery for mobile. i want to back up files from the local storage using jszip. below is a code snippet of what i have done...
if (localStorageKeys.length > 0) {
for (var i = 0; i < localStorageKeys.length; i++) {
var key = localStorageKeys[i];
if (key.search(_instrumentId) != -1) {
var data = localStorage.getItem(localStorageKeys[i])
var zip = new JSZip();
zip.file(localStorageKeys[i] + ".txt", data);
var datafile = document.getElementById('backupData');
datafile.download = "DataFiles.zip";
datafile.href = window.URL.createObjectURL(zip.generate({ type: "blob" }));
}
else {
}
}
}
in the code above am looping through the localstorage content and saving ezch file in a text format. the challenge that am facing is how to create several text files inside DataFiles.zip as currently am only able to create one text file inside the zipped folder. Am new to javascript so bare with any ambiguity in my question.
thanks in advance.
Just keep calling zip.file().
Look at the example from their documentation page (comments mine):
var zip = new JSZip();
// Add a text file with the contents "Hello World\n"
zip.file("Hello.txt", "Hello World\n");
// Add a another text file with the contents "Goodbye, cruel world\n"
zip.file("Goodbye.txt", "Goodbye, cruel world\n");
// Add a folder named "images"
var img = zip.folder("images");
// Add a file named "smile.gif" to that folder, from some Base64 data
img.file("smile.gif", imgData, {base64: true});
zip.generateAsync({type:"base64"}).then(function (content) {
location.href="data:application/zip;base64," + content;
});
The important thing is to understand the code you've written - learn what each line does. If you do this, you'd realize that you just need to call zip.file() again to add another file.
Adding to #Jonathon Reinhart answer,
You could also set both file name and path at the same time
// create a file and a folder
zip.file("nested/hello.txt", "Hello World\n");
// same as
zip.folder("nested").file("hello.txt", "Hello World\n");
If you receive a list of files ( from ui or array or whatever ) you can make a compress before and then archive. The code is something like this:
function upload(files){
var zip = new JSZip();
let archive = zip.folder("test");
files.map(function(file){
files.file(file.name, file.raw, {base64: true});
}.bind(this));
return archive.generateAsync({
type: "blob",
compression: "DEFLATE",
compressionOptions: {
level: 6
}
}).then(function(content){
// send to server or whatever operation
});
}
this worked for me at multiple json files. Maybe it helps.
In case you want to zip files and need a base64 output, you can use the below code-
import * as JSZip from 'jszip'
var zip = new JSZip();
zip.file("Hello.json", this.fileContent);
zip.generateAsync({ type: "base64" }).then(function (content) {
const base64Data = content