javascript - form - jquery ajax post
Cómo generar una imagen en miniatura después de agregar una imagen dentro de un tipo de entrada="archivo" en un formulario y enviarlos en el mismo formulario (4)
Después de una mejor búsqueda en línea encontré la respuesta a mi pregunta.
Es posible combinar lienzo junto con la API de archivos .
Intente cargar cualquier imagen en la demostración a continuación y ver que aparecerá una nueva miniatura generada en el lado derecho del formulario.
DEMO: http://jsfiddle.net/a_incarnati/fua75hpv/
function handleImage(e){
var reader = new FileReader();
reader.onload = function(event){
var img = new Image();
img.onload = function(){
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img,0,0);
}
img.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
DerekR ha dado una buena respuesta a esta pregunta:
Tengo un formulario que permite al usuario subir una foto. Después de que el usuario haya enviado el formulario, me gustaría generar en el front-end una miniatura para cada imagen y luego almacenarla en el servidor.
Por razones de seguridad, no es posible alterar el valor de un campo de entrada de archivo, entonces, ¿cómo puedo enviar al servidor algunas imágenes en miniatura generadas en el front-end en js?
¿Es posible en el front-end generar una miniatura del conjunto de imágenes en el campo de archivo de entrada antes de enviar el formulario? ¿Y luego enviar ambos al mismo tiempo?
He encontrado este tutorial más simple pero potente . Simplemente crea un elemento img
y, utilizando el objeto fileReader, asigna su atributo de origen como el valor de la entrada del formulario
function previewFile() {
var preview = document.querySelector(''img'');
var file = document.querySelector(''input[type=file]'').files[0];
var reader = new FileReader();
reader.onloadend = function () {
preview.src = reader.result;
}
if (file) {
reader.readAsDataURL(file);
} else {
preview.src = "";
}
}
<input type="file" onchange="previewFile()"><br>
<img src="" height="200" alt="Image preview...">
Pensé que valdría la pena agregar una respuesta más contemporánea y citar los documentos web de MDN .
Puede agregar un detector de eventos para "cambiar" en el elemento de entrada y luego mostrar una miniatura de la imagen seleccionada accediendo a la lista de archivos a través de this.files
(como se muestra en un ejemplo de MDN). Aquí hay una implementación reciente de la mía. uploadWatermark es un <input type="file></input>
uploadWatermark.addEventListener(''change'', function(){
const file = this.files[0];
if (file.type.startsWith(''image/'')) {
const img = document.createElement(''img'');
const watermarkPreview = document.getElementById("uploaded-watermark");
img.classList.add("prev-thumb");
img.file = file;
watermarkPreview.appendChild(img);
const reader = new FileReader();
reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }})(img);
reader.readAsDataURL(file);
}
});
TL; DR: ver el JSFiddle
Como quería subir imágenes a través de una API y mostrar una vista previa de la imagen (dos cosas que realmente se prestaban bien entre sí), se me ocurrió esto:
(function(angular) {
angular
.module(''app'')
.directive(''inputFilePreview'', [function() {
var canvas, mapToModel, elementScope;
/**
* To be fired when the image has been loaded
*/
var imageOnLoad = function(){
canvas.width = this.width;
canvas.height = this.height;
canvas.getContext("2d").drawImage(this,0,0);
};
/**
* To be fired when the FileReader has loaded
* @param loadEvent {{}}
*/
var readerOnLoad = function(loadEvent){
var img = new Image();
img.onload = imageOnLoad;
img.src = loadEvent.target.result;
if(mapToModel) {
setModelValue(elementScope, mapToModel, img.src);
}
};
/**
* This allows us to set the value of a model in the scope of the element (or global scope if the
* model is an object)
* @param scope {{}}
* @param modelReference {string}
* @param value {*}
*/
var setModelValue = function(scope, modelReference, value) {
// If the model reference refers to the propery of an object (eg. "object.property")
if(~modelReference.indexOf(''.'')) {
var parts = modelReference.split(''.'', 2);
// Only set the value if that object already exists
if(scope.hasOwnProperty(parts[0])) {
scope[parts[0]][parts[1]] = value;
return;
}
}
scope[modelReference] = value;
};
/**
* The logic for our directive
* @param scope {{}}
* @param element {{}}
* @param attributes {{}}
*/
var link = function(scope, element, attributes) {
elementScope = scope;
canvas = document.getElementById(attributes.inputFilePreview);
if(attributes.hasOwnProperty(''mapToModel'')) {
mapToModel = attributes.mapToModel;
}
element.on(''change'', function(changeEvent) {
var reader = new FileReader();
reader.onload = readerOnLoad;
reader.readAsDataURL(changeEvent.target.files[0]);
});
};
return {
restrict: ''A'',
link: link
};
}]);
})(angular);
Los dos elementos necesarios para que funcione la vista previa son:
<canvas id="image-preview"></canvas>
<input type="file" data-input-file-preview="image-preview" data-map-to-model="image.file" />
Fragmento sigue:
(function (angular) {
angular.module(''app'', [])
.directive(''inputFilePreview'', [function () {
var canvas, mapToModel, elementScope;
/**
* To be fired when the image has been loaded
*/
var imageOnLoad = function () {
canvas.width = this.width;
canvas.height = this.height;
canvas.getContext("2d").drawImage(this, 0, 0);
};
/**
* To be fired when the FileReader has loaded
* @param loadEvent {{}}
*/
var readerOnLoad = function (loadEvent) {
var img = new Image();
img.onload = imageOnLoad;
img.src = loadEvent.target.result;
if (mapToModel) {
setModelValue(elementScope, mapToModel, img.src);
}
};
/**
* This allows us to set the value of a model in the scope of the element (or global scope if the
* model is an object)
* @param scope {{}}
* @param modelReference {string}
* @param value {*}
*/
var setModelValue = function (scope, modelReference, value) {
// If the model reference refers to the propery of an object (eg. "object.property")
if (~modelReference.indexOf(''.'')) {
var parts = modelReference.split(''.'', 2);
// Only set the value if that object already exists
if (scope.hasOwnProperty(parts[0])) {
scope[parts[0]][parts[1]] = value;
return;
}
}
scope[modelReference] = value;
};
/**
* The logic for our directive
* @param scope {{}}
* @param element {{}}
* @param attributes {{}}
*/
var link = function (scope, element, attributes) {
elementScope = scope;
canvas = document.getElementById(attributes.inputFilePreview);
if (attributes.hasOwnProperty(''mapToModel'')) {
mapToModel = attributes.mapToModel;
}
element.on(''change'', function (changeEvent) {
var reader = new FileReader();
reader.onload = readerOnLoad;
reader.readAsDataURL(changeEvent.target.files[0]);
});
};
return {
restrict: ''A'',
link: link
};
}])
.controller(''UploadImageController'', [
''$scope'',
function ($scope) {
$scope.image = {
title: ''Test title''
};
$scope.send = function (data) {
$scope.sentData = JSON.stringify(data, null, 2);
return false;
};
}]);
})(angular);
canvas {
max-height: 300px;
max-width: 300px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<form data-ng-app="app" data-ng-controller="UploadImageController">
<input data-ng-model="image.title" />
<br />
<canvas id="image-preview"></canvas>
<br />
<input type="file" data-input-file-preview="image-preview" data-map-to-model="image.file" />
<br />
<input type="submit" data-ng-click="send(image)" />
<pre>{{sentData}}</pre>
</form>