I wonder if someone can help me with this as I'm new to JavaScript.
I have a form, and within it I have a file input. However, when a file is uploaded I need to manipulate it and add new properties. So I extract the file from the input like so:
let uploadedFile = [];
for (let val of this.files) {
uploadedFile.push(val)
}
for (val of uploadedFile){
//Check file extension to classify the file type:
let extension = val.name.split('.')
extension = String((extension[extension.length-1]).toLowerCase());
let fileType = val.type;
//Arrays to hold extensions types we want to identify
const imageExtensions = ['jpeg','jpg','png']
const documentExtensions = ['xls','xlsx','csv','pdf']
//Classify files and push to global files array
if (imageExtensions.includes(extension)){
let newFile = new File([val], `${crname}-nr-${FileCount}.${extension}`, {type: `${fileType}`});
newFile.originalName = `${val.name}`
globalFilesArray.push(newFile);
}
}
So as you can see the new file objects are pushed to an array named 'globalFilesArray'
Now in Flask i'm typically accessing the form data using the request module.
Must I now pass the array into a separate hidden file input so I can access it when the entire form is submitted?
I'm a bit stumped with this because I need this to happen only when the form is submitted so I can also access the rest of the input fields in the form.
Related
I have a project to create PDF out from google form and send multiple PDF through email in Google Script,
The relevant CODE segment is as follows ,
if(TF_Samples!= null){
//Generating Lab Reports for TAPE LIFT
for (var Sample_Number in TF_Samples) {
//Creating Report File - Word Version
Template_Doc = Tape_Template_Doc ;
Report_File_Word = Template_Doc.makeCopy(Report_Folder_Word);
Report_File_Word.setName(data[0]+"-TAPE LIFT");
Opened_Report_Doc = DocumentApp.openById(Report_File_Word.getId());
//Getting the Content of the Report & Replacing the Fields
Report_Body = Opened_Report_Doc.getBody();
Report_Body.replaceText("{{ Client Address }}",data[2]);
Report_Body.replaceText("{{ Sample Date }}",data[1]);
Report_Body.replaceText("{{ Sample Number }}",TF_Samples[Sample_Number]);
//Saving & Closing the Report
Opened_Report_Doc.saveAndClose();
//Creating PDF version of Report
Blob_PDF = Report_File_Word.getAs(MimeType.PDF);
Report_PDF_Version = Report_Folder_PDF.createFile(Blob_PDF).setName(data[0]+"-SPORE TRAPE");
}
}
I managed to send email with single attachment but since here I am looping through a for loop I don't know how to do that.
Create a global array and push within each loop iteration the file into the array
Sample modification:
...
var files = [];
for (var Sample_Number in TF_Samples) {
...
Report_PDF_Version = Report_Folder_PDF.createFile(Blob_PDF).setName(data[0]+"-SPORE TRAPE");
files.push(Report_PDF_Version);
}
GmailApp.sendEmail(recipient, subject, body, {attachments:files});
...
as specified in the documentation, the attachment argument must be an array of blobs.
So, instead of converting the blob to a drive file just send the blobs like this :
Blob_PDF = Report_File_Word.getAs(MimeType.PDF);
and push these blobs in an array one by one.
The argument will then be valid.
I need to parse a PDF file with a lot of Acroform fields and extract the field name (/T in PDF markup) and value (/V in PDF markup) for each field. I'd like to do this client side in JavaScript but I'm not finding existing examples or libraries that seem to do this. Does any one have any suggestions on how to approach it?
Edit: I want to do this client side for performance reasons. I will be taking the field values from the PDF and saving them to a database. But for some of the fields I will need to prompt for additional input before saving. I'd like to do that all on the client and then send the values to the server for saving instead of uploading the PDF to the server, parsing it on the server, sending the fields that need additional input back to the client, and then sending those results to be saved.
The company I work for has PDFTron WebViewer SDK which can you read through all the form fields, read/edit the values, all client side in the browser, and you can also allow the user to view the entire PDF and manually fill in any fields.
Sample: https://www.pdftron.com/webviewer/demo/pdf-forms
I need to parse a PDF file with a lot of Acroform fields and extract the field name (/T in PDF markup) and value (/V in PDF markup) for each field.
You can see live code in the pdf-forms sample linked above, but this code below would iterate all fields and print the value, if any, to the console.
viewerElement.addEventListener('ready', function() {
var viewerInstance = viewer.getInstance();
const docViewer = viewerInstance.docViewer;
const annotManager = docViewer.getAnnotationManager();
const fieldManager = annotManager.getFieldManager();
const checkField = (field) => {
// Do something with data
const { name, value } = field;
console.log(name + ' ' + value);
// Check children fields
field.children.forEach(checkField);
}
docViewer.on('annotationsLoaded', function() {
fieldManager.forEachField(checkField);
});
});
I will be taking the field values from the PDF and saving them to a
database.
If you just want the field values, you can get that easily from WebViewer, in PDF ISO XFDF XML format, which you can send to your server and merge to the PDF using any PDF SDK that supports XFDF. This way, you can avoid transferring the entire PDF back and forth, and just send the much smaller form field values as XML.
var xmlXfdfFieldData = annotManager.exportAnnotations({fields:true, widgets:false, links:false});
for some of the fields I will need to prompt for additional input
before saving.
The WebViewer UI/UX is completely customizable so you can interact/prompt the user on which fields to update.
This sample below shows how to change color and opacity of form fields, which would be a starting point you can use to apply your own business logic.
https://www.pdftron.com/documentation/web/guides/form-samples#customizing-form-fields
It turns out not to be that hard to parse what I need out of the PDF and a library would probably be overkill. Here's the code I'm using:
function importPdf(event) {
const reader = new FileReader();
reader.onload = function () {
const matches = reader.result.match(/((obj)[\s\S]*?(endobj))/g);
matches.forEach(match => {
const tIndex = match.indexOf('/T (');
const vIndex = match.indexOf('/V (');
if(tIndex > -1 && vIndex > -1) {
const fieldNameSegment = match.substring(tIndex + 4);
const fieldNameValue = fieldNameSegment.substring(0,fieldNameSegment.indexOf(')'));
const valueSegment = match.substring(vIndex + 4);
const dataValue = valueSegment.substring(0, valueSegment.indexOf(')'));
console.log(fieldNameValue, dataValue);
}
});
}
reader.readAsText(event.target.files[0]);
}
<input type="file" id="file-input" onchange="importPdf(event)">
I'm trying to create a meteor-package to import JSON-files to collections in a mongoDB. But I'm not quite sure, if this is possible.
So I want the user to upload a JSON-file. In a input-field the user also types the collection-name which has to be used for the import. After this the JSON-array should be saved to the given collection.
HTML:
<template name="importJSON">
<form id="importJson">
<input type="text" id="collection">
<input type="file" id="file">
</form>
</template>
meteor:
Template.importJSON.events({
'submit #importJson': function(e){
e.preventDefault();
var collection = e.target.collection.value;
var obj = JSON.parse(response);
db.collection.insert(obj);
}
});
So I have three problems with that:
1) How do I have to do the upload itself, as the file should be uploaded temporarily
2) How can I use the collection name given in the input-field?
3) How do I import the data in a correct way? Insert would just append the new data to the existing data, wouldn't it?
So to answer your three problems:
1) How do I have to do the upload itself, as the file should be uploaded temporarily
If all you need to do is read the file, then insert it into a collection. In that case you do not need to even upload the file. Just read the file in client side. Here is an article on Reading files in JavaScript using the File APIs.
2) How can I use the collection name given in the input-field?
Say the collection name given in the input-field is products and assume you have a sample data file like this:
{
"name": "Product",
"id": "Product identifier",
"name": "Name of the product",
"price": "9990",
"tags": ["tag1", "tag2"]
}
At this point you need to decide how you do this. If you already have a Products collection on server side.
<your app name>/lib/collections/products.js
Products = new Meteor.Collection('Products');
Then in your client side code:
var rawproducts = (content of the file you read using the File API -- as mentioned above)
var newproducts = JSON.parse(rawproducts);
for (var i = 0; i < newproducts.length; i++) {
Products.insert(newproducts[i]);
}
You can also test this out locally by creating a local only collection.
//pass null as collection name, it will create
//local only collection
Products = new Mongo.Collection(null);
for (var i = 0; i < newproducts.length; i++) {
Products.insert(newproducts[i]);
}
Note: If you use a local only collection your data is still on the client. You'll need to sync that with the server (as described above) for persistence.
3) How do I import the data in a correct way? Insert would just append the new data to the existing data, wouldn't it?
Importing the data as shown above will keep on appending the data. You may want to think about how to de-dupe the data or completely overwrite the existing data.
Hope this helps.
Update:
How to delete all the elements from a collection?
Products.remove({}) // remove every product
I am storing File list in cookies so that if I navigate to another page and come back to this page, I want all the files which were selected by user previously.
This code I am using it to store the data in cookies.
if(!angular.isUndefined(filelist)) {
$cookies.filelist = JSON.stringify(filelist).toString();
}
Below code I am using to create filelist object from the files selected by user
$('#fileupload').on('fileuploadadd', function (e, data) {
for(var i = 0; i < data.files.length; i++){
filelist.push(data.files[i])
}
});
Code to retrieve data from cookies
if($cookies.filelist != null && $cookies.filelist != 'undefined' && $cookies.filelist != 'null') {
filelist = $.merge(filelist,JSON.parse($cookies.filelist));
}
When i am storing this filelist object it is of "File" type and when I am retrieve it is of "Object". How can I type cast my object to file object? Is it a correct approach I am following?
You would be better off setting up a file structure on your server for storing the files, then use a database to store the URL of the files, when adding the url to the database you can also add the url to your cookies or in session variables, so when you come back to the page you have all your url's that point to the files. I don't understand why you need the actual file object itself. This is only used by <input file /> to upload to disk.
I am trying to make a small web app using django and javascript however I have ran into a problem.
In my model I have an entity name "entry" which has attributes id, name, location_lat and location_lon all as char arrays. I pass entrys associated to a certain sport to a "map.html" file using the following code:
def sportpage(request,sportname):
t = get_template('map.html')
try:
entry_list = Feature.objects.filter(sport=sportname)
except BaseException:
raise Http404
sport_list = Sport.objects.all().order_by('name')
context = RequestContext(request,{'sport_list':sport_list,'entry_list':entry_list, 'page_title':sportname})
return HttpResponse(t.render(context))
and in the JavaScript file I attempt to read "entry_list" in using:
var data = "{{entry_list|safe}}";
However the data only contains a list of the entry names but not the location_lat or location_lon attributes. How would I gain access to these?
Thank you very much for any help