Javascript handling multiple files upload - javascript

I'm working on a project with the following steps:
Creating the form with multiple images upload
Previewing, remove images on queue before upload
Handling the file input value before submit
Here is my code
var fileList = [];
function toObject(arr) {
var rv = {};
for (var i = 0; i < arr.length; ++i)
rv[i] = arr[i];
return rv;
}
//Image prev
// Multiple images preview in browser
var imagesPreview = function (input, imageContainer) {
if (input.files) {
var filesAmount = input.files.length;
$(imageContainer).html('');
for (i = 0; i < filesAmount; i++) {
var reader = new FileReader();
reader.onload = function (event) {
var html = '<div class="image-item col-sm-6 col-md-4 col-lg-3"><div class="image-wrapper">' +
' <img src="'
+ event.target.result + '"/></div></div>';
$(html).appendTo(imageContainer);
}
var files = input.files;
fileList.push(files[i]);
reader.readAsDataURL(input.files[i]);
}
input.files = toObject(fileList);
}
};
$('#input-image').on('change', function () {
imagesPreview(this, '.image-container');
});
<div class="image-item">
<!-- input the image from user -->
<input id="input-image" type="file" name="photos[]" multiple>
<hr>
<div class="image-container row">
<!-- Previewing the image thumbnail -->
</div>
</div>
My questions: Can I set the value of the input-image with fileList variable because I set it but error occurs

Sry, a bit tired, will not go into depth or solve the hole thing...
There is only one way to change the value of file inputs and that is with another FileList instance. the only way you can get them is with some new api's so it won't work in all browsers. I made a function to help you with that.
var fileList = [];
// only way to change input[type=file] value is with a other FileList instance
// and this is the only way to construct a new FileList
function createFileList(a) {
a = [].slice.call(Array.isArray(a) ? a : arguments)
for (var c, b = c = a.length, d = !0; b-- && d;) d = a[b] instanceof File
if (!d) throw new TypeError('expected argument to FileList is File or array of File objects')
for (b = (new ClipboardEvent('')).clipboardData || new DataTransfer; c--;) b.items.add(a[c])
return b.files
}
// This is what you got to do later when they remove a image
//
// this will trigger a change event so you maybe want to temporary
// turn off the change event listener
//
// input.files = createFileList(fileList)
// Image prev
// Multiple images preview in browser
function imagesPreview(input, imageContainer) {
$(imageContainer).empty();
var URL = window.URL || window.webkitURL;
var $html = $(
'<div class="image-item col-sm-6 col-md-4 col-lg-3">'+
'<div class="image-wrapper"> <img></div></div>'
);
$.each(input.files, function(i, file) {
var $clone = $html.clone()
// could be a good idea to revoke url also
$clone.find('img').attr('src', URL.createObjectURL(file))
$clone.appendTo(imageContainer);
fileList.push(file);
});
}
$('#input-image').on('change', function () {
imagesPreview(this, '.image-container');
});
The other solution is to append each file into a formdata and send the form using ajax

Related

I can't print the list on the screen

I want to list my json data as checkboxlist. I wrote this code. I'm printing this way. I don't know where I'm doing wrong. I get my jSON data from excel file. textarea comes out as "undefined undefined" . Could you help?
HTML CODE:
<div class="example">
<form enctype="multipart/form-data">
<input id="upload" type=file name="files[]">
</form>
<textarea
id="data"
class="form-control text-area-style"
rows=35
cols=120>
</textarea>
</div>
JS CODE:
function ExcelToJSON() {
var list;
document.getElementById("upload").addEventListener("change", handleFileSelect, false);
this.parseExcel = function(file) {
var reader = new FileReader();
reader.onload = function(e) {
var data = e.target.result;
var workbook = XLSX.read(data, {
type: "binary"
});
workbook.SheetNames.forEach(function(sheetName) {
// Here is your object
var XL_row_object = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]);
var json_object = JSON.stringify(XL_row_object);
list = JSON.parse(json_object);
console.log(list);
jQuery().val(json_object);
list.forEach(function() {
$('#data).append(' < input name = "accesories"
type = "checkbox"
value = "'+list.id+'" / > '+list.name+' < br / > ');
});
})
};
reader.onerror = function(ex) {
console.log(ex);
};
reader.readAsBinaryString(file);
};
};
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
var xl2json = new ExcelToJSON();
xl2json.parseExcel(files[0]);
}
list.forEach(function() {
$('#data).append(' < input name = "accesories"
type = "checkbox"
value = "'+list.id+'" / > '+list.name+' < br / > ');
});
})
list does not have the attributes id and name (are undefined), you are iterating over list but you are not using the iterated item.
list.forEach(function(item) { // <= forEach calls for every list item this function with the item as argument
$('#data).append(' < input name = "accesories"
type = "checkbox"
value = "'+item.id+'" / > '+item.name+' < br / > ');
});
})
Hint:
Use the build in Browser Debugger it helps a lot, to understand JS.
With Chrome press F12 and set a breakpoint in the foreach function, then execute your code and it will break on the given line, then you will see all variables in your scope. (In your case you will se that list is an array and don't have id and name as property)

readAsDataURL is not a blob, yet the images show

I have a file input which then preview the images after adding. The images show, but I get:
Uncaught TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'."
What's causing this, surely they wouldn't show still?
$('#image-upload-input').on('change', function() {
var files = document.getElementById('image-upload-input').files;
for (var key in files) {
if (files[key]) {
var reader = new FileReader();
reader.onload = function(e) {
$('.image-upload-container').append('<img src="'+ e.target.result +'" style="width: 100px;">');
}
reader.readAsDataURL(files[key]);
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="image-upload-input" type="file" multiple>
<div class="image-upload-container"></div>
You are misusing the for( in ) loop. As it iterates it chokes on the length property - which is not a Blob Object. This happens because the for( in ) iterates over all (enumerable) object properties and not just "own properties". Reference
You have two choices:
Stick to the traditional (and always works) for() loop
Use the for( of ) loop
The for( of ) loop will only iterate "own properties" while the traditional for() loop will always, always work when a length property is available.
$('#image-upload-input').on('change', function() {
var files = document.getElementById('image-upload-input').files;
for(file of files) {
if (file) {
var reader = new FileReader();
reader.onload = function(e) {
$('.image-upload-container').append('<img src="'+ e.target.result +'" style="width: 100px;">');
}
reader.readAsDataURL(file);
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="image-upload-input" type="file" multiple>
<div class="image-upload-container"></div>
Good example of few issues together.
Exception you get - is because files isn't real array, so for ... in - iterates over "0", "1"... "item","length" keys.
You can't use async function inside loop without isolating the scope
My personal opinion: don't use jQuery if you can :-)
$('#image-upload-input').on('change', function() {
var files = document.getElementById('image-upload-input').files;
for (var key=0; key < files.length; key++) {
(function(){
var reader = new FileReader();
var file = files[key];
reader.onload = function(e) {
var img = document.createElement('img');
img.style= "width:100px";
img.src = reader.result;
$('.image-upload-container').append($(img));
}
reader. readAsDataURL(file);
})();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="image-upload-input" type="file" multiple>
<div class="image-upload-container"></div>
I would have ditched the FileReader for URL.createObjectURL and just use a regular for loop
$('#image-upload-input').on('change', function() {
var files = document.getElementById('image-upload-input').files;
for (var i = 0; i < files.length; i++) {
var url = URL.createObjectURL(files[i]);
$('.image-upload-container').append('<img src='+ url +' style="width: 100px;">');
}
});
and possible added this extra attribute to the input
accept="image/*"

Upload Multiple Image using multiple file control in asp.net mvc 4.0 (angular js)

I am using Visual Studio 2012 Express with Framework 4.5 MVC.
I am also using Angular Js for the first time.
I have a view page that contains the multiple browse (file) button that will be use for upload single image by selecting each of them individually with my form data.
The problem is that by using submit button I am not able to get the images but I got the form data.
I want to get the images with the form data using Angular js.
I have already referred below posts but not getting the solution:
LINK 1
LINK 2
Please anyone help me to solve out this problem, would be appreciated.
I have a sample code for the uploading of multiple image using angularjs.
This link might help you: https://jsfiddle.net/n9tL7cdr/1/
<div ng-app="test">
<div ng-controller="UploadCtrl">
<table>
<tr ng-repeat="i in [1, 2, 3, 4]">
<td>{{i}}</td>
<td>
<input type="file" name="file" onchange="angular.element(this).scope().photoChanged(this.files)" /> </td>
<td>
<img ng-src="{{ image[$index].dataUrl }}" height="50px" />
</td>
</tr>
</table>
</div>
CONTROLLER:
angular.module('test', []);
angular.module('test').controller('UploadCtrl', function ($scope, $timeout) {
// Variable for image.
$scope.image = {
dataUrl: []
};
$scope.fileReaderSupported = window.FileReader != null;
$scope.photoChanged = function (files, index) {
if (files != null) {
var file = files[0];
var index = this.$index; // index of image.
if ($scope.fileReaderSupported && file.type.indexOf('image') > -1) {
$timeout(function () {
var fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = function (e) {
$timeout(function () {
$scope.image[index] = {dataUrl: e.target.result}; // Retrieve the image.
});
}
});
}
}
};
});
Here i find the solution using HttpPostedFileBase and Form Collection.
public ActionResult AddImageUpload(IEnumerable<HttpPostedFileBase> files,FormCollection fc )
{
ImageUpload IU = new ImageUpload();
IU.MaterialId = Convert.ToInt32((fc["MaterialId"]).Replace("number:",""));
IU.CategoryId = Convert.ToInt32((fc["CategoryId"]).Replace("number:", ""));
string tr = fc["hdnSub"].ToString();
string result = null;
string Message, fileName, actualFileName;
Message = fileName = actualFileName = string.Empty;
bool flag = false;
//HttpPostedFileBase f= IU.ImageP;
string[] SubAssemblyId = (tr.Split(','));
int i = 0;
string databaseid = null;
for (int j=0 ; j<files.Count(); j++)
{
var fileContent = Request.Files[j];
if (fileContent.FileName != "")
{
databaseid = SubAssemblyId[i];
string fn = DateTime.Now.ToShortDateString().Replace("/", "") + DateTime.Now.TimeOfDay.Hours + DateTime.Now.TimeOfDay.Minutes + DateTime.Now.TimeOfDay.Seconds + DateTime.Now.TimeOfDay.Milliseconds + Path.GetExtension(fileContent.FileName);
fileName = fn;
try
{
if (fileContent != null && fileContent.ContentLength > 0)
{
var inputStream = fileContent.InputStream;
var path = Path.Combine(Server.MapPath("/Images/Product/"), fn);
using (var fileStream = System.IO.File.Create(path))
{
inputStream.CopyTo(fileStream);
}
}
}
catch (Exception)
{
}
}
i++;
}
return RedirectToAction("ImageUpload");
}

Jquery upload files when open button is pressed

i have the following code, the issue i have is that i am getting a error of e.originalEvent.dataTransfer is undefined.
my code is as follows
HTML
Select images: <input type="file" id='fileupload' name="userfile[]" multiple>
Javascript is as follows
var hot = $('#fileupload');
hot.change(function (e)
{
e.preventDefault();
var files = e.originalEvent.dataTransfer.files;
//send dropped files to Server
handleFileUpload(files,hot);
});
function handleFileUpload(files,obj)
{
for (var i = 0; i < files.length; i++)
{
var fd = new FormData();
var e = document.getElementById("child_id");
fd.append('userfile[]', files[i]);
var filename=files[i].name;
var status = new createStatusbar(obj,files[i]); //Using this we can set progress.
status.setFileNameSize(files[i].name,files[i].size);
sendFileToServer(fd,status,filename);
}
}
The attribute files belongs to the input field. This you'll get by the target attribute.
If I test the setting above, I have success with this descriptor:
e.originalEvent.target.files
Then, files is an array of File objects, containing name, lastModifiedDate, type etc.

Javascript Image Preview for page with lots of forms

I have a bunch of forms on a page that allow a user to edit information for each respective form. One of the inputs for the form is an image upload.
The forms are of the form below:
<form class="myForm" ...>
<div class="imagePreview"></div>
<input type="file" name="myImage" onchange="handleFiles(this.files)" />
</form>
And I have javascript to handle the image preview as follows:
function handleFiles(files) {
$(".obj").remove();
for (var i = 0; i < files.length; i++) {
var file = files[i];
var imageType = /image.*/;
if (!file.type.match(imageType)) {
continue;
}
var pic_div = document.getElementById("imagePreview");
var img = document.createElement("img");
img.classList.add("obj");
img.file = file;
pic_div.appendChild(img);
var reader = new FileReader();
reader.onload = (
function(aImg) {
return function(e) {
aImg.src = e.target.result;
};
}
)(img);
reader.readAsDataURL(file);
}
}
I want to replace the line:
var pic_div = document.getElementById("imagePreview");
with the appropriate line. This is where I am getting confused. I don't know how to refer to the div of class "imagePreview" for THIS FORM of class myForm.
Any help is much appreciated.
The problem is that you're getting the div with the Id imagePreview, when the div in the form have the imagePreview CSS class, what you can do is either give the div the required id, more less like this:
<div id="imagePreview"></div>
Or, if you will have multiple divs with the same class get them using jQuery like this:
$(".imagePreview").each(function(index){
//Do Something
});
Or:
var pic_div = $(".imagePreview")[0]

Categories

Resources