Javascript: Selecting photo using showOpenFilePicker - javascript

I am accessing the user selected photo using showOpenFilePicker. but after selecting the photo, the input file data is null. It looks like he didn't. so I'm trying to manually add the user selected photo to the input file element. but still it doesn't happen. what should I do?
html:
<div class="col-md-3 iniTpe">
<div class="form-group">
<label for="researchPhoto">Example file input</label>
<input name="researchPhoto" onclick="Research.OpenFiles(event)" type="file" accept="image/*" class="form-control-file" id="researchPhoto">
</div>
</div>
javascript:
OpenFiles: async function (event) {
event.preventDefault();
let files = await window.showOpenFilePicker({
types: [
{
description: 'İmage Files',
accept: {
'image/*': ['.png', '.gif', '.jpeg', '.jpg'],
},
},
],
excludeAcceptAllOption: true,
multiple: false,
});
let fileData = await files[0].getFile();
document.getElementById("researchPhoto").files[0] = fileData;
console.log(document.getElementById("researchPhoto").files[0])//comes null. normally it should not be null
}

I believe you need one additional step after .getFile(). Per MDN getFile returns a blob. You probably want to use a method like .text() to get the text of the file or another function mentioned on in the documentation such as createBitmapImage() to process the file as an image.

Related

Access a pdf file from views.py which is created by Js in a Django project

I am trying to render with HTML to pdf in my Django project. I am using html2pdf package form js and render my html into pdf by following link: youtubelink.
my template:
<div class="container-fluid py-5 bg-light">
<div class="col-xl-10 bg-white" id="pdf_portion">
<p>Lots of staff is in this div. I just skip those unnecessary things in this question.</p>
</div>
</div>
<button class="btn btn-primary" id="download"> download pdf</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.9.2/html2pdf.bundle.js"></script>
<script type="text/javascript">
window.onload = function () {
document.getElementById("download")
.addEventListener("click", () => {
const invoice = this.document.getElementById("pdf_portion");
console.log(invoice);
console.log(window);
var opt = {
margin: 0.8,
filename: 'myfile.pdf',
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 4 },
jsPDF: { unit: 'in', format: 'A4', orientation: 'portrait' }
};
html2pdf().from(invoice).set(opt).save();
})
}
</script>
Here the 'download' button gives us the option to download the pdf. I need to send the pdf in my views.py in any method, thus I will able to save it in my database's filefield.
Please suggest How can I able to access that pdf file in my views.py.
The html2pdf package comes with the functionality to handle the generated pdf instead of directly downloading them. It's outputPdf function takes the desired data format as input and returns the output.
Currently supported data-formats are:
arraybuffer
blob
bloburi
datauristring
datauri
It can be used as followed:
const elem = document.getElementById('html'); //element whose pdf is to be made
html2pdf().from(elem).outputPdf('arraybuffer').then((result) => {
// write your desired code here for sendin results to django views
});
Now in order to send this data to backend, you can simply use AJAX post request in this function.

I've got a weird behaviour on req.body on put request on a specific field

I've created a form to save a new real estate to MongoDB, using multer for multi-part form data and body-parser.
Everything works fine except the "rooms" in the "put" (EDIT) route, which are returned as an array, instead of a single value, which makes absolutely no sense, as everything else works just fine.
I've tried to translate the data from the array to a single numerical value, but that does not work as if I try to edit the document once more the new value is pushed in the array instead of replacing the old one.
//EDIT PUT ROUTE
router.put("/immobili/:_id/edit",
upload.fields([{ name: 'estateImages', maxCount: 30 },
{ name: 'document', maxCount: 1 }]),
(req, res) => {
// IMAGES LOGIC SKIPPED HERE AS NOT PERTINENT
Estate.findOneAndUpdate({ _id: requestedId }, {
rooms: req.body.rooms, //BUGGED
squareFeets: req.body.squareFeets, //WORKS CORRECTLY
//CALLBACK ...
}}
// result of console.log of req.body.rooms and req.body.squareFeets
rooms: [ '2', '' ],
squareFeets: 120
//EJS FORM DATA
<form action="/estates/<%= estate._id %>/edit?_method=PUT" method="POST"
enctype="multipart/form-data">
//INPUT NOT WORKING:
<input name="rooms" value="<%= estate.rooms %>"></input>
//INPUT THAT WORKS:
<input name="superficie" value="<%= estate.squareFeets %>"></input>
<input type="submit" value="Publish">
</form>
When you get an array, is because you have multiple inputs with that name:
<input name="rooms" value="<%= estate.rooms %>"></input>
<input name="rooms" value="other-value"></input>
So if you don't want an array, change the input name to the second one.
Omg I have been SO stupid, I've put two inputs with the same name value in the form, thus those values were being saved as an array.
I'm so sorry about this. Thanks for your time!

set processor in $http PUT request not saving proper data

Relatively new to javascript and angular. I'm using an elasticsearch instance to ingest/index different files. The webapp should have the capability to allow the user to upload multiple files, which will then be processed using the ingest processor and indexed into ES. I'm using angular-base64-upload to extract the base64 data. The following is what I've tried so far.
The html:
<div ng-switch-when="upload">
...
<input type="file" ng-model="obj.files" name="files"
base-sixty-four-input multiple>
...
<div ng-show="obj.files.length != 0">
<button class="btn btn-primary" type="submit" ng-click="ingest()">
Index All {{obj.files.length}} Files
</button> <br><br>
</div>
</div>
The javascript ingest() function code in my controller:
//Ingesting multiple files
$scope.obj = {files: []};
$scope.ingest = function () {
$scope.obj.files.forEach(function (file){
var fname = file.filename.replace(/\.[^/.]+$/, "");
var fdata = file.base64;
//Creating the pipeline
console.log('filename is: ' + fname);
$http({
url: 'http://192.168.100.30:9200/_ingest/pipeline/attachment',
method: "PUT",
data: {
"description" : "Indexing files",
"processors" : [
{
"set" : {
"field" : "filename",
"value" : fname
},
"attachment" : {
"field" : "data"
}
}
]
}
})
.then(function(allowed){
//Indexing the document
$http({
url: 'http://192.168.100.30:9200/my_index4/my_type/'+fname+'?pipeline=attachment', //unique ID for every document, ensures that there are no overlaps
method: "PUT",
data: {
"data": fdata
}
})
})
})
}
The console logging is just used for debug purposes.
The issue I'm running into is while elastic stores the file under the proper _id, which in my case is the filename, it does not store the proper field: filename. For instance, if I upload 2 files called hello.txt and world.txt, ES will store both files with hello and world as their respective _ids, but the filename field is often swapped or just generally, incorrect. I've ran the code multiple times to see if there was a pattern, and I can't really seem to find one.
The console.logs show that fname is the proper filename before the first http, after it, and after the second http, which is why I'm confused as to why the set processor is not storing it properly.
I may not have clearly explained the issue very well, as it's kind of convoluted. Let me know if anything needs extra explanation. Thanks!

Node.js: How to write input values of a formular into a JSON file when the submit button is pressed?

NEW: MORE SPECIFIC DESCRIPTION
I'm programming a website with different products of different types. Each product has a detail page with a comment function. The path of a products detail site looks like http://localhost:3000/details/type/name. When a user fills the form to write a comment and presses the submit button, all data should be append to the product type's JSON file which looks like:
type1.json
[
{
"name": "Product1",
"description": "Description1",
"comments":[
{
"user": "Matthew",
"message": "Very Good!",
"timestamp": "2017-03-17T17:51Z"
},{
"user": "Lea",
"message": "Nice",
"timestamp": "2017-03-10T13:29Z"
}
]
},
{
"name": "Product2",
"description": "Description2",
"comments":[
{
"user": "Ann",
"message": "This is very useful!",
"timestamp": "2017-02-02T19:30Z"
},{
"user": "Tim",
"message": "Awesome",
"timestamp": "2017-04-01T20:25Z"
}
]
]
This is the part of my HTML file which contains the form:
details.html
<form action="" method="POST" id="commentForm">
<div class="form-group">
<input type="text" id="name"
placeholder="Name" class="form-control" name="name"/>
</div>
<div class="form-group">
<textarea cols="30" rows="5" class="form-control" id="message" placeholder="Message" name="message"></textarea>
</div>
<div class="form-group">
<div class="col-md-6 text-center">
<button type="reset" class="btn btn-default">
<span class="glyphicon glyphicon-remove"></span>
Reset
</button>
</div>
<div class="col-md-6 text-center">
<button type="submit" class="btn btn-success">
<span class="glyphicon glyphicon-ok"></span>
Send
</button>
</div>
</div>
</form>
This is the relevant part of my JavaScript file:
details.js
$(function () {
$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
$("#commentForm").bind("submit", function(evt) {
console.log(JSON.stringify($("#commentForm").serializeObject()));
$.ajax({
url: window.location.pathname,
type: "POST",
contentType: "application/json",
data: JSON.stringify($("#commentForm").serializeObject()),
success: function(data) {
console.log('success');
console.log(JSON.stringify(data));
},
});
return false;
});
});
Now, the question is: What to write in the app.js?
In the following is an excerpt of the current app.js.
app.js
const express = require("express");
const app = express();
const fs = require('fs');
const path = require("path");
const jsonfile = require('jsonfile');
const bodyParser = require('body-parser');
app.use(bodyParser.json());
const type1File = __dirname + "/data/type1.json";
...
app.post("/details/:typ/:name", function (req, res) {
if (req.params.typ == "type1") {
const apps = readJsonFile(type1File);
res.send(getProduct(apps, req));
???What to write here???
}
...
});
function readJsonFile(file) {
try {
const data = fs.readFileSync(file);
return JSON.parse(data);
} catch (e) {
console.log(file + "could not be read. " + e);
return [];
}
}
What should I add? How is it possible that the data will be written to the "comment"-key of the right JSON object? Please help me, I spent a lot of time trying out different things, but nothing works right.
Note: This answer was written before the question was rewritten:
https://stackoverflow.com/posts/43213085/revisions
This question is so general that it's hard to give you any specific answer. But if you want persistent data in your app then you should use a database.
Some databases like Mongo, Postgres or Redis need to be run as standalone application either on the same or on a different server. Some embedded databases like SQLite don't need a standalone process and can be run directly in your application. There are multiple choices of databases and it's something that you have to choose yourself for your particular case. But you should choose some database to store the data.
It's not that it is impossible to write to JSON files on updates and then read those files as needed, but the amount of work that you'd have to do to synchronize the access to the data so that no two requests to write happen at the same time and no read happens while a write is in progress, all that without accidentally blocking the event loop in the process and handling multiple requests concurrently, is something greatly more difficult than just using any database as intended.
Some databases like Mongo will let you store any JSON documents (actually it stores BSON but for the user it's just like JSON). Using a document database like Mongo or CouchDB will be most similar to having JSON files but using a relational database could work as well. Pretty much every persistent data is kept in databases. If you can write your own database that stores data in JSON files then by all means do it if you need, but if you can't then just use the right tool for the job.
That having been said, if you still insist on reading and writing JSON files, here's what to do:
To write data as JSON into files, you will need to use JSON.stringify() and fs.writeFile().
To read JSON data from files, you will need to use fs.readFile() and JSON.parse().
Things to keep in mind:
JSON.parse() and JSON.stringify() must always be wrapped in a try/catch block or otherwise your app will crash (or use tryjson module from npm).
Never use methods of the fs modules with "Sync" in their name or otherwise your app will be blocked from serving requests.
You need to implement locking and synchronization of the access to files or otherwise your data will get corrupted - this is the most difficult and most important part, and this is the reason why people use databases for that sort of things.

How do I submit a real-time validated form with Semantic UI and Meteor?

I have run into a huge problem with my form, which I validate in real time using Semantic UI.
The HTML:
<form class="ui form pin-form">
<div class="field">
<label>Email</label>
<input placeholder="name#example.com" name="email_input" type="text">
</div>
<div class="ui buttons">
<input type="submit" class="ui submit positive disabled button login-button" value="Log in">
</div>
</form>
I added the <form> tag myself and made the submit into an input so that I could access the regular submit form.
The real time validation comes from Semantic UI and a Meteor package: https://github.com/avrora/live-form-validator
On template render I do this:
if (!this._rendered) {
this._rendered = true;
pinForm = $('.ui.form.pin-form');
pinForm.form({
my_text_input: {
identifier: 'email_input',
rules: [
{
type: 'empty',
prompt: 'Type your email address'
},
{
type: 'email',
prompt: 'This is not yet a valid email address'
}
]
}
},
{
inline: true,
on: 'blur',
transition: 'slide down',
onSuccess: function () {
var submitButton = $('.ui.submit.button')
submitButton.removeClass('disabled')
return false
},
onFailure: function() {
var submitButton = $('.ui.submit.button')
submitButton.addClass('disabled')
}
})
}
The big problem here is that with return false it doesn't submit the form at all even when click the submit button, and without it it submits the form in real time, which I don't want!
Can anyone see a workaround or do I need to switch validation somehow?
If you want to do a Meteor.call, you could try doing it in the onSuccess function. The package does ask you to save the data manually within the onSuccess function.
The following code logged the email twice.
onSuccess: function () {
console.log("Email: ", $("input[name=email_input]").val());
// Submit your form here using a Meteor.call maybe?
return false;
},
You could alternatively look at aldeed:autoform for handling forms in Meteor.
This could be the stupidest question on all of SO. (Don't worry, I asked the question so I'm only dissing myself!)
Semantic UI literally provides the on: change setting, which will validate the form in real time instead of on: blur which it is set to now.
Oh, man...

Categories

Resources