There's an example from MDN on how to use FileReader to show a preview image:
function handleFiles(files) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var imageType = /^image\//;
if (!imageType.test(file.type)) {
continue;
}
var img = document.createElement("img");
img.classList.add("obj");
img.file = file;
preview.appendChild(img); // Assuming that "preview" is the div output where the content will be displayed.
var reader = new FileReader();
reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
reader.readAsDataURL(file);
}
}
I'm wondering how to use this in a Vue component. It seems to me the asynchronous part isn't that easy to handle, but I'm new to Vue, and maybe that's an advanced feature.
Create a component with an <img :src="src" id="img> tag and src property in it's data object. You could pass an idx prop from parent component along with a file if you would like to make a gallery and and it to an img id, because as we reference an image by id we need unique id for each img element.
Create a method loadPicture
loadPicture(file) {
let self = this;
let img = document.getElementById('img');
var reader = new FileReader();
reader.onload = function(e) {
self.src = e.target.result;
}
reader.readAsDataURL(file);
}`
Then call this method in mounted lifecycle
mounted() {
this.loadPicture();
}
Working example: https://jsfiddle.net/8dnhh23o/
Multiple images example: https://jsfiddle.net/o1037uks/
Related
Below are my snippet right now its printing all canvas in single page. I want to print the each canvas in a new page.
I have use Fabricjs to render the canvas from json. Other pdf library not able to print the canvas it download empty PDF so i try JSPDF But stuck in a point.
DEMO
<script>
var jsPDF = window.jspdf.jsPDF;
var html2canvas = window.html2canvas;
function downloadpdf(){
console.log('Inside downloadpdf ');
var quotes = document.getElementById('generatePDF');
html2canvas(quotes, {
onrendered: function(canvas) {
canvas.getContext('2d');
var HTML_Width = canvas.width;
var HTML_Height = canvas.height;
var top_left_margin = 15;
var PDF_Width = HTML_Width+parseInt(top_left_margin*2);
var PDF_Height = parseInt(PDF_Width*1.5)+parseInt(top_left_margin*2);
var canvas_image_width = HTML_Width;
var canvas_image_height = HTML_Height;
var totalPDFPages = Math.ceil(HTML_Height/PDF_Height)-1;
var pages = $('#generatePDF .canvas-container').length;
console.log('height => '+canvas.height+" width => "+canvas.width+'totalpage => '+pages);
var imgData = canvas.toDataURL("image/jpeg", 1.0);
var pdf = new jsPDF('p', 'pt', [PDF_Width, PDF_Height]);
pdf.addImage(imgData, 'JPG', top_left_margin, top_left_margin,canvas_image_width,canvas_image_height);
for (var i = 1; i <= pages; i++) {
//pdf.addPage(PDF_Width, PDF_Height);
pdf.addPage();
let margin=-parseInt(PDF_Height*i)+parseInt(top_left_margin*4);
if(i>1){
margin= parseInt(margin+i*8);
}
pdf.addImage(imgData, 'JPG', top_left_margin, margin,canvas_image_width,canvas_image_height);
}
pdf.save("HTML-Document.pdf");
}
});
}
</script>
public UploadFile()
{
//File Data
this.filePath = $("#inputFile").val();
var file = $("#inputFile").get(0).files[0];
var reader = new FileReader();
reader.onload = function (evt) {
var fileContent = reader.result;
var x = fileContent.bytes;
}
Your question isn't completely clear, but here's some sample code that may help. This should be valid TypeScript code, which reads a file from input element #inputFile and displays the text from it in a div with id #divMain.
$("#inputFile").on('change', null, (e) => {
var input = <HTMLInputElement>e.target;
var files = input.files;
var f:File = files[0];
var reader = new FileReader();
var name = f.name;
console.log("File name: " + name);
reader.onload = function (e) {
var target: any = e.target;
var data = target.result;
$("#divMain").text(data);
};
reader.readAsText(f);
});
Scenario: In our application a user can create a invoice by filling in certain fields on a Knockout view. This invoice can be previewed, via another Knockout page. I want to use the preview url within our PDF creator (EVOPdf), so we can provide the user with a PDF from this invoice.
To preview the invoice we load the data (on document ready) via an ajax-request:
var InvoiceView = function(){
function _start() {
$.get("invoice/GetInitialData", function (response) {
var viewModel = new ViewModel(response.Data);
ko.applyBindings(viewModel, $("#contentData").get(0));
});
};
return{
Start: _start
};
}();
My problem is within the data-binding when the PDF creator is requesting the url: the viewModel is empty. This makes sense because the GetInitialData action is not called when the PDF creator is doing the request. Calling this _start function from the preview page directly at the end of the page does not help either.
<script type="text/javascript">
$(document).ready(function() {
InvoiceView.Start();
});
</script>
Looking at the documentation of EvoPdf, JavaScript should be executed, as the JavaScriptEnabled is true by default: http://www.evopdf.com/api/index.aspx
How could I solve this, or what is the best approach to create an pdf from a knockout view?
Controller action code:
public FileResult PdfDownload(string url)
{
var pdfConverter = new PdfConverter();
// add the Forms Authentication cookie to request
if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
pdfConverter.HttpRequestCookies.Add(
FormsAuthentication.FormsCookieName,
Request.Cookies[FormsAuthentication.FormsCookieName].Value);
}
var pdfBytes = pdfConverter.GetPdfBytesFromUrl(url);
return new FileContentResult(pdfBytes, "application/pdf");
}
Javascript:
var model = this;
model.invoiceToEdit = ko.observable(null);
model.downloadInvoice = function (invoice) {
model.invoiceToEdit(invoice);
var url = '/invoice/preview';
window.location.href = '/invoice/pdfDownload?url=' + url;
};
The comment of xdumaine prompted me to think into another direction, thank you for that!
It did take some time for the Ajax request to load, but I also discovered some JavaScript (e.g. knockout binding) errors along the way after I put a ConversionDelay on the pdf creator object
pdfConverter.ConversionDelay = 5; //time in seconds
So here is my solution for this moment, which works for me now:
To start the process a bound click event:
model.downloadInvoice = function (invoice) {
var url = '/invoice/preview/' + invoice.Id() + '?isDownload=true';
window.open('/invoice/pdfDownload?url=' + url);
};
which result in a GET resquest on the controller action
public FileResult PdfDownload(string url)
{
var pdfConverter = new PdfConverter { JavaScriptEnabled = true };
// add the Forms Authentication cookie to request
if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
pdfConverter.HttpRequestCookies.Add(
FormsAuthentication.FormsCookieName,
Request.Cookies[FormsAuthentication.FormsCookieName].Value);
}
pdfConverter.ConversionDelay = 5;
var absolutUrl = ToAbsulte(url);
var pdfBytes = pdfConverter.GetPdfBytesFromUrl(absolutUrl);
return new FileContentResult(pdfBytes, "application/pdf");
}
The Pdf creator is requesting this action on the controller, with isDownload = true (see bound click event):
public ActionResult Preview(string id, bool isDownload = false)
{
return PartialView("PdfInvoice", new InvoiceViewModel
{
IsDownload = isDownload,
InvoiceId = id
});
}
Which returns this partial view:
PartialView:
// the actual div with bindings etc.
#if (Model.IsDownload)
{
//Include your javascript and css here if needed
#Html.Hidden("invoiceId", Model.InvoiceId);
<script>
$(document).ready(function () {
var invoiceId = $("#invoiceId").val();
DownloadInvoiceView.Start(invoiceId);
});
</script>
}
JavaScript for getting the invoice and apply the knockout bindings:
DownloadInvoiceView = function() {
function _start(invoiceId) {
$.get("invoice/GetInvoice/" + invoiceId, function(response) {
var viewModel = new DownloadInvoiceView.ViewModel(response.Data);
ko.applyBindings(viewModel, $("#invoiceDiv").get(0));
});
};
return {
Start: _start
};
}();
DownloadInvoiceView.ViewModel = function (data) {
var model = this;
var invoice = new Invoice(data); //Invoice is a Knockout model
return model;
};
I'm trying out Dart, but I cant figure out, how to send an image from the user to the server. I have my input-tag, and i can reach this in the DART code, but i cant seem to read from it. Im trying something like:
InputElement ie = document.query('#myinputelement');
ie.on.change.add((event){<br/>
InputElement iee = document.query('#myinputelement');<br/>
FileList mfl = iee.files;<br/>
File myFile = mlf.item(0);<br/>
FileReader fr = new FileReader();
fr.readAsBinaryString(myFile);
String result = fr.result; //this is always empty
});
With the html containing:
<input type="file" id="myinputelement">
I really hope you cant help me, im kinda stuck. I might just be missing how to do the onload for the filereader, or maybe im doing it totally wrong.
The FileReader API is asynchronous so you need to use event handlers.
var input = window.document.querySelector('#upload');
Element log = query("#log");
input.addEventListener("change", (e) {
FileList files = input.files;
Expect.isTrue(files.length > 0);
File file = files.item(0);
FileReader reader = new FileReader();
reader.onLoad = (fileEvent) {
print("file read");
log.innerHTML = "file content is ${reader.result}";
};
reader.onerror = (evt) => print("error ${reader.error.code}");
reader.readAsText(file);
});
you also need to allow file uploads from to your browser, which can be done in Chrome by starting it with the flag --allow-file-access-from-files
This is how to read a file using dart:html.
document.querySelector('#myinputelement`).onChange.listen((changeEvent) {
List fileInput = document.querySelector('#myinputelement').files;
if (fileInput.length > 1) {
// More than one file got selected somehow, could be a browser bug.
// Unless the "multiple" attribute is set on the input element, of course
}
else if (fileInput.isEmpty) {
// This could happen if the browser allows emptying an upload field
}
FileReader reader = new FileReader();
reader.onLoad.listen((fileEvent) {
String fileContent = reader.result;
// Code doing stuff with fileContent goes here!
});
reader.onError.listen((itWentWrongEvent) {
// Handle the error
});
reader.readAsText(fileInput[0]);
});
It's not necessary (any more) to use dart:dom FileReader instead of the one from dart:html.
Your code should work if you add an event listener to the file reader, like this:
FileReader fr = new FileReader();
fr.on.load.add((fe) => doSomethingToString(fe.target.result));
fr.readAsBinaryString(myFile);
My attempt
void fileSelected(Event event) async {
final files = (event.target as FileUploadInputElement).files;
if (files.isNotEmpty) {
final reader = new FileReader();
// ignore: unawaited_futures
reader.onError.first.then((evt) => print('error ${reader.error.code}'));
final resultReceived = reader.onLoad.first;
reader.readAsArrayBuffer(files.first);
await resultReceived;
imageReference.fileSelected(reader.result as List<int>);
}
}
Thanks to the help from this post, I got it to work. I still utilized my event handler in the input tag and made sure that I DID NOT import both dart:io and dart:html, only dart:html is needed.
This is what my final AppComponent looked like.
import 'dart:html';
import 'package:angular/angular.dart';
#Component(
selector: 'my-app',
styleUrls: ['app_component.css'],
templateUrl: 'app_component.html',
directives: [coreDirectives],
)
class AppComponent {
// Stores contents of file upon load
String contents;
AppComponent();
void fileUpload(event) {
// Get tag and the file
InputElement input = window.document.getElementById("fileUpload");
File file = input.files[0];
// File reader and event handler for end of loading
FileReader reader = FileReader();
reader.readAsText(file);
reader.onLoad.listen((fileEvent) {
contents = reader.result;
});
}
}
This is what my template looks like:
<h1>File upload test</h1>
<input type="file" (change)="fileUpload($event)" id="fileUpload">
<div *ngIf="contents != null">
<p>Hi! These are the contents of your file:</p>
<p>{{contents}}</p>
</div>
I'm running a website, where I'd like to upload files with Drag 'n Drop, using the HTML5 File API and FileReader. I have successfully managed to create a new FileReader, but I don't know how to upload the file. My code (JavaScript) is the following:
holder = document.getElementById('uploader');
holder.ondragover = function () {
$("#uploader").addClass('dragover');
return false;
};
holder.ondragend = function () {
$("#uploader").removeClass('dragover');
return false;
};
holder.ondrop = function (e) {
$("#uploader").removeClass('dragover');
e.preventDefault();
var file = e.dataTransfer.files[0],
reader = new FileReader();
reader.onload = function (event) {
//I shoud upload the file now...
};
reader.readAsDataURL(file);
return false;
};
I also have a form (id : upload-form) and an input file field (id : upload-input).
Do you have any ideas?
P.S. I use jQuery, that's why there is $("#uploader") and others.
Rather than code this from scratch, why not use something like html5uploader, which works via drag n drop (uses FileReader etc.): http://code.google.com/p/html5uploader/
EDIT: apparently we respondents are supposed to tend to our answers forever more, for fear for down-votes. The Google Code link is now dead (four years later), so here's a jQuery plugin that is very similar: http://www.igloolab.com/jquery-html5-uploader/
You'll want to extract the base64 encoded file contents and ajax them over tot the server.
JavaScript
var extractBase64Data;
extractBase64Data = function(dataUrl) {
return dataUrl.substring(dataUrl.indexOf(',') + 1);
};
// Inside the ondrop event
Array.prototype.forEach.call(event.dataTransfer.files, function(file) {
var reader;
if (!file.type.match(options.matchType)) {
return;
}
reader = new FileReader();
reader.onload = function(event) {
var contentsBase64;
if (event.target.readyState === FileReader.DONE) {
contentsBase64 = extractBase64Data(event.target.result);
return $.post(someURL, {
contentsBase64: contentsBase64
});
}
};
reader.readAsDataURL(file);
});
CoffeeScript
extractBase64Data = (dataUrl) ->
dataUrl.substring(dataUrl.indexOf(',') + 1)
# Inside the ondrop event
Array::forEach.call event.dataTransfer.files, (file) ->
return unless file.type.match(options.matchType)
reader = new FileReader()
reader.onload = (event) ->
if event.target.readyState == FileReader.DONE
contentsBase64 = extractBase64Data(event.target.result)
$.post someURL,
contentsBase64: contentsBase64
reader.readAsDataURL(file)