Is Parse's Javascript file upload broken? - javascript

I've been trying to save a user-uploaded image to parse for the longest time, and nothing seems to work -- even when following their documentation.
Below is the handler I use for the onChange() on a multiple file upload. At first I was concerned about multiple file uploads, but at this point just saving one image doesn't work.
function fileHandler(event) {
var files = event.target.files;
stopPictures = [];
$("#stop-img-container").empty();
if (files[0] != null) {
$("#stop-img-container").show();
for (var i = 0; i < files.length; i++) {
var file = files[i];
var picReader = new FileReader();
picReader.addEventListener("load",function(event){
var picFile = event.target;
var image = $("<img/>",{
"title": picFile.name,
"class": "stop-image",
"src": picFile.result
}).appendTo("#stop-img-container");
var name = picFile.name;
var dataFile = picFile.result;
var base64str = dataFile.substring(dataFile.indexOf("base64,")+7,dataFile.length);
var parseFile = new Parse.File(name,{base64:base64str}); // saving logs 404 Not Found from POST to "http://api.parse.com/1/files"
var parseFile = new Parse.File(name,dataFile); // saving logs "Uncaught Creating a Parse.File from a String is not yet supported."
var parseFile = new Parse.File(name,file); // saving logs 404 Not Found from POST to "http://api.parse.com/1/files"
var parseFile = new Parse.File(name,base64str); // saving logs "Uncaught Creating a Parse.File from a String is not yet supported."
parseFile.save().then(function (savedFile) {
stopPictures.push(savedFile);
alert("worked");
});
});
picReader.readAsDataURL(file);
}
} else {
$("#stop-img-container").hide();
}
}
There's some extraneous stuff here, but basically it collects the user's selected files, displays them for them once they've finished loading, and then creates them as a Parse file. I've left it in to show that at least something is working as it properly locally stores and previews the user's selected files.
I have included three different ways of creating the same Parse file. However, all of them fail when I try to save to Parse in any way.
Parse's Javascript API docs says that any of these should work fine. But they lie, or I'm an idiot.
Anyone have any idea why this doesn't seem to work? Seems like a pretty critical aspect of their API is broken completely -- which I find hard to imagine.
EDIT: I'm also positive I'm properly parsing (lower case p) the base64 string as this site confirms the appropriate image and works.

I experienced the same problem.
Finally I found what causes the problem.
It's a "file name".
I suspect the file name in tuckerchapin's example is null.
var name = picFile.name;
I wrote the example with React.
this code works fine.
class ImageUpload extends React.Component {
onChange(e) {
var file = e.target.files[0];
var parseFile = new Parse.File(file.name, file);
Parse.User.current().set("icon",parseFile);
Parse.User.current().save();
}
handleSubmit(e) {
e.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input type="file" onChange={this.onChange.bind(this)} />
</form>
);
}
}

Related

how to read a static file from url in javascript to create an array

I searched but I don't find, I am coding a simulator and I want to do the calculus using javascript, the simulator takes 2 kind of entries. The first entries are given by user, this part is done. The second part is a lot of coefficient which are stored in csv/tsv file, the file is uploaded on the server. And I am not able to read this file, I found a lot of code on how to convert csv to array and I think that I will be able to do it alone. For now I am doing step by step so I just want to read the csv file to put it inside a table, when I use the code shown it works if I use an < input type="file" > but I am not able to make it works with a static url. Can You help me?
function myprocessFile()
{
var fileSize = 0;
var theFile = document.getElementById("myFile").files[0];
document.getElementById("toto").innerHTML = blob;
if (theFile)
{
var table = document.getElementById("myTable");
var headerLine = "";
var myReader = new FileReader();
myReader.onload = function(e)
{
// CREATE TABLE
}
myReader.readAsText(theFile);
}
return false;
}
You could use the fetch API :
fetch('url/to/your/csv/file')
.then(function(response) {
return response.text()
})
.then(function(csv) {
// convert your csv to an array
});

Disable the possibility to upload files for user

I'm building a service for users where I must have private files.
Actually, with Cloud Code, I can control the download flux, through a function. But, how I can prevent a hacker to use the javascript console and upload his files ? He will get a link, which he can share with anyone without restriction and at my charges.
const file = Parse.File('hackerFile', hackerFileArray);
file.save().then(() => console.log(file.url)) // Now, he have a free file hosting.
Is there a way to completely remove this feature for everyone, except the master key ?
Example of hosting a file on http://todolist.parseapp.com/
Open the console in your browser then
var script = document.createElement('script');
script.src = '//www.parsecdn.com/js/parse-1.6.14.min.js'; // Because of their version.
document.head.appendChild(script);
Parse.initialize("0Oq3tTp9JMvd72LOrGN25PiEq9XgVHCxo57MQbpT", "vUFy2o7nFx3eeKVlZneYMPI2MBoxT5LhWNoIWPja"); // Found in their sources
var reader = new FileReader();
var input = document.createElement('input');
input.type = 'file';
document.body.appendChild(input);
// Then choose a file from the browser. I choosen a picture.
reader.onloadend = function() {
var file = new Parse.File('hackFile', {base64: reader.result});
file.save().then(function() {
console.log(file.url());
})
};
reader.readAsDataURL(input.files[0]);
Then you have a link. I got http://files.parsetfss.com/ae2ddbce-9cc0-4e1a-a16d-52ec5fdb7570/tfss-8fccfba0-ccf7-41cd-8f42-75f0a3478262-hackFile
Haven't tried this, but think it could work:
1) Add a beforeSave function on whatever class you're looking to prevent this behavior on.
2) In the beforeSave, check request.object.dirtyKeys() and iterate through each of those keys on the newly created object.
3) If the value associated with one of those dirtyKeys is a file, don't allow the file to save: response.error
Parse.Cloud.beforeSave(Parse.User, function(request, response) {
var dirtyKeys = request.object.dirtyKeys();
for (var i = 0; i < dirtyKeys.length; ++i) {
var dirtyKey = dirtyKeys[i];
if (isUnwantedFile(request.object, dirtyKey)) {
response.error("User is not allowed to store files");
return;
}
}
response.success();
});
//note this function is untested -- I'm not sure what type a user-created file would be,
//but basically if you can figure that out, substitute it in here
function isUnwantedFile(obj, key){
return typeof obj[dirtyKey] === Parse.File
}

Uploading files to parse.com with javascript

I'm attempting to upload an array of files to parse using javascript with the following code:
html:
<fieldset>
<input type="file" name="fileselect" id="fileselect" multiple></input>
<input id="uploadbutton" type="button" value="Upload"> </input>
</fieldset>
JS:
$('#uploadbutton').click(function () {
var fileUploadControl = $("#fileselect")[0];
if (fileUploadControl.files.length > 0) {
var file = fileUploadControl.files[0];
var name = "style.css";
var parseFile = new Parse.File(name, file);
var filesArray = [parseFile];
}
parseFile.save().then(function() {
// The file has been saved to Parse.
}, function(error) {
// The file either could not be read, or could not be saved to Parse.
});
var newStore = new Parse.Object("FileStore");
newStore.set("files", filesArray);
newStore.save();
});
I am uploading to a class I have called FileStore with key "files" which is set to an array currently, and I would like to have hold an array of files. Is this the best way to go about uploading multiple files to parse? The code for me isn't working right now. My aim is to have multiple files associated with each object in my class.
Be careful with async code. Currently your code will have a race condition that will most likely fail because you call newStore.save() before parseFile.save() is finished.
Those 3 lines dealing with newStore should be inside the success handler for parseFile.save(), e.g.:
parseFile.save().then(function() {
// The file has been saved to Parse.
var newStore = new Parse.Object("FileStore");
newStore.set("files", filesArray);
newStore.save();
}, function(error) {
// The file either could not be read, or could not be saved to Parse.
});
When you get to saving multiple files you'll need to wait for all of them to finish before moving to the next step. You can chain your promises together to run in Series or in Parallel.
For what you want Parallel would work fine:
var fileSavePromises = [];
// assuming some code that creates each file has stored the Parse.File objects in an
// array called "filesToSave" but not yet called save
_.each(filesToSave, function(file) {
fileSavePromises.push(file.save());
});
Parse.Promise.when(fileSavePromises).then(function() {
// all files have saved now, do other stuff here
var newStore = new Parse.Object("FileStore");
newStore.set("files", filesToSave);
newStore.save();
});
I have managed to solve this with the help of #Timothy code, full code after edit:
var fileUploadControl = $("input[type=file]")[0];
var filesToSave = fileUploadControl.files;
var fileSavePromises = [];
// assuming some code that creates each file has stored the Parse.File objects in an
// array called "filesToSave" but not yet called save
_.each(filesToSave, function(file) {
var parseFile = new Parse.File("photo.jpg", file);
fileSavePromises.push(
parseFile.save().then(function() {
// The file has been saved to Parse.
$.post("/i", {
file: {
"__type": "File",
"url": parseFile.url(),
"name": parseFile.name()
}
});
})
);
});
Parse.Promise.when(fileSavePromises).then(function() {
// all files have saved now, do other stuff here
window.location.href = "/";
});

document generation only works the first time

I'm using openxml in my HTML5 mobile app to generate word documents on the mobile device.
In general openxml works fine and straight forward, but I'm struggling with an annyoing problem.
The document generation only works the first time after I've started the app. This time I can open and view the document. Restart the app means:
- Redeploy from development machine
- Removing the app from the task pane (pushing aside; I assume the app is removed then?)
The second time I get the message the document is corrupted and I'm unable to view the file
UPDATE:
I can't reproduce this behaviour when I'm running the app connected to the remote debugger without having a breakpoint set. Doing it this way I always get a working document.
I doesn't make a difference wether I do any changes on the document or not. Simply open and saving reproduce this error.
After doing some research I've found that structure of the docx.zip file of the working and the corrupt file is the same. They also have the same file length. But in the corrupt docx there are some files I've found some files having a wrong/invalid CRC. See here an example when trying to get a corrupt file out of the zip. Other files are working as expected.
The properties for this file are->
(CRC in a working version is: 44D3906C)
Code for processing the doc-template:
/*
* Process the template
*/
function processTemplate(doc64, callback)
{
"use strict";
console.log("PROCESS TEMPLATE");
var XAttribute = Ltxml.XAttribute;
var XCData = Ltxml.XCData;
var XComment = Ltxml.XComment;
var XContainer = Ltxml.XContainer;
var XDeclaration = Ltxml.XDeclaration;
var XDocument = Ltxml.XDocument;
var XElement = Ltxml.XElement;
var XName = Ltxml.XName;
var XNamespace = Ltxml.XNamespace;
var XNode = Ltxml.XNode;
var XObject = Ltxml.XObject;
var XProcessingInstruction = Ltxml.XProcessingInstruction;
var XText = Ltxml.XText;
var XEntity = Ltxml.XEntity;
var cast = Ltxml.cast;
var castInt = Ltxml.castInt;
var W = openXml.W;
var NN = openXml.NoNamespace;
var wNs = openXml.wNs;
var doc = new openXml.OpenXmlPackage(doc64);
// add a paragraph to the beginning of the document.
var body = doc.mainDocumentPart().getXDocument().root.element(W.body);
var tpl_row = ((doc.mainDocumentPart().getXDocument().descendants(W.tbl)).elementAt(1).descendants(W.tr)).elementAt(2);
var newrow = new XElement(tpl_row);
doc.mainDocumentPart().getXDocument().descendants(W.tbl).elementAt(1).add(newrow);
// callback(doc);
var mod_file = null;
var newfile;
var path;
if (doc != null && doc != undefined ) {
mod_file = doc.saveToBlob();
// Start writing document
path = "Templates";
newfile = "Templates/Bau.docx";
console.log("WRITE TEMPLATE DOCUMENT");
fs.root.getFile("Templates/" + "MyGenerated.docx", {create: true, exclusive: false},
function(fileEntry)
{
fileEntry.createWriter(
function(fileWriter)
{
fileWriter.onwriteend = function(e) {
console.log("TEMPLATE DOCUMENT WRITTEN:"+e.target.length);
};
fileWriter.onerror = function(e) {
console.log("ERROR writing DOCUMENT:" + e.code + ";" + e.message);
};
var blobreader = new FileReader();
blobreader.onloadend = function()
{
fileWriter.write(blobreader.result); // reader.result contains the contents of blob as a typed array
};
blobreader.readAsArrayBuffer(mod_file);
},
null);
}, null);
};
Any ideas what I'm doing wrong?
Thanks for posting about the error. There were some issues with jszip.js that I encountered when I was developing the Open XML SDK for JavaScript.
At the following link, there is a sample javascript app that demonstrates generating a document.
Open XML SDK for JavaScript Demo
In that app you can save multiple DOCXs, one after another, and they are not corrupted.
In order to work on this issue, I need to be able to re-produce locally. Maybe you can take that little working web app and replace parts with your parts until it is generating invalid files?
Cheers, Eric
P.S. I am traveling and have intermittent access to internet. If you can continue the thread on OpenXmlDeveloper.org, then it will help me to answer quicker. :-)
What made it work for me, was changing the way of adding images (Parts) to the document. I was using the type "binary" for adding images to document. I changed this to "base64"
So I changed the source from:
mydoc.addPart( "/word/"+reltarget, openXml.contentTypes.png, "binary", fotodata ); // add Image Part to doc
to:
mydoc.addPart( "/word/"+reltarget, openXml.contentTypes.png, "base64", window.btoa(fotodata) ); // add Image Part to doc

file input does not update except in Chrome

I have a local program which writes a JSON object to a file so that a JavaScript can pick up its data and process it. The file is selected using an <input> object:
<form id = "getfiles">
<input type = "file" multiple id = "files" />
</form>
with the following JS function setInterval to repeat every 300ms. However, when the file changes, only Google Chrome reloads the file and processes the new content; I have to manually reselect the file on the page in IE 10 and Firefox 20.
function speakText()
{
var thefile = document.getElementById('files').files[0];
var lastChanged = thefile.lastModifiedDate;
var reader = new FileReader();
reader.onload = function(event)
{
var lcd = document.getElementById("last_change_date");
if (!lcd)
{
var spanLastChanged = document.createElement("span");
spanLastChanged.id = "last_change_date";
spanLastChanged.innerText = lastChanged;
console.log(lastChanged);
document.body.appendChild(spanLastChanged);
}
else
{
// compare lastChanged with last_change_date
var last_known_change = Date.parse(lcd.innerText);
// var last_known_change = Date.parse(thefile.lastModifiedDate);
if (last_known_change !== Date.parse(lastChanged))
{
console.log("Something is new since " + lcd.innerText);
var fileContent = event.target.result;
var commands = JSON.parse(fileContent);
handleJSON(fileContent);
lcd.innerText = lastChanged;
}
}
}
reader.readAsText(thefile, "UTF-8");
}
Firefox and IE are doing the right thing per spec: the File objects associated with a file input are supposed to be immutable snapshots of a file at the point when the File object was created. It's a known bug in WebKit/Blink that they just store a reference to the file's data, so that mutating the data will change what the File object sees.
In fact, the WebKit/Blink behavior is a privacy bug: when a user selects a file in a file input, they are giving a web page permission to read the data of the file at that time, not for all future versions of the file! Which is why the spec is written as it is.

Categories

Resources