I tried different approach but still can't find the solution.
I need to upload an image with my form with fields (title, description, and 2 image).
My system uses csrf of CodeIgniter. And I use this simple third party file uploader (http://jasny.github.io/bootstrap) fileinput.js
var Fileinput = function (element, options) {
this.$element = $(element)
this.$input = this.$element.find(':file')
if (this.$input.length === 0) return
this.name = this.$input.attr('name') || options.name
this.$hidden = this.$element.find('input[type=hidden][name="' + this.name + '"]')
if (this.$hidden.length === 0) {
this.$hidden = $('<input type="hidden">').insertBefore(this.$input)
}
this.$preview = this.$element.find('.fileinput-preview')
var height = this.$preview.css('height')
if (this.$preview.css('display') !== 'inline' && height !== '0px' && height !== 'none') {
this.$preview.css('line-height', height)
}
this.original = {
exists: this.$element.hasClass('fileinput-exists'),
preview: this.$preview.html(),
hiddenVal: this.$hidden.val()
}
this.listen()
}
Fileinput.prototype.listen = function() {
this.$input.on('change.bs.fileinput', $.proxy(this.change, this))
$(this.$input[0].form).on('reset.bs.fileinput', $.proxy(this.reset, this))
this.$element.find('[data-trigger="fileinput"]').on('click.bs.fileinput', $.proxy(this.trigger, this))
this.$element.find('[data-dismiss="fileinput"]').on('click.bs.fileinput', $.proxy(this.clear, this))
},
Fileinput.prototype.change = function(e) {
var files = e.target.files === undefined ? (e.target && e.target.value ? [{ name: e.target.value.replace(/^.+\\/, '')}] : []) : e.target.files
e.stopPropagation()
if (files.length === 0) {
this.clear()
return
}
this.$hidden.val('')
this.$hidden.attr('name', '')
this.$input.attr('name', this.name)
var file = files[0]
if (this.$preview.length > 0 && (typeof file.type !== "undefined" ? file.type.match(/^image\/(gif|png|jpeg)$/) : file.name.match(/\.(gif|png|jpe?g)$/i)) && typeof FileReader !== "undefined") {
var reader = new FileReader()
var preview = this.$preview
var element = this.$element
reader.onload = function(re) {
var $img = $('<img>')
$img[0].src = re.target.result
files[0].result = re.target.result
element.find('.fileinput-filename').text(file.name)
// if parent has max-height, using `(max-)height: 100%` on child doesn't take padding and border into account
if (preview.css('max-height') != 'none') $img.css('max-height', parseInt(preview.css('max-height'), 10) - parseInt(preview.css('padding-top'), 10) - parseInt(preview.css('padding-bottom'), 10) - parseInt(preview.css('border-top'), 10) - parseInt(preview.css('border-bottom'), 10))
preview.html($img)
element.addClass('fileinput-exists').removeClass('fileinput-new')
element.trigger('change.bs.fileinput', files)
}
reader.readAsDataURL(file)
} else {
this.$element.find('.fileinput-filename').text(file.name)
this.$preview.text(file.name)
this.$element.addClass('fileinput-exists').removeClass('fileinput-new')
this.$element.trigger('change.bs.fileinput')
}
},
Fileinput.prototype.clear = function(e) {
if (e) e.preventDefault()
this.$hidden.val('')
this.$hidden.attr('name', this.name)
this.$input.attr('name', '')
//ie8+ doesn't support changing the value of input with type=file so clone instead
this.$input.val('')
this.$preview.html('')
this.$element.find('.fileinput-filename').text('')
this.$element.addClass('fileinput-new').removeClass('fileinput-exists')
if (e !== undefined) {
this.$input.trigger('change')
this.$element.trigger('clear.bs.fileinput')
}
},
Fileinput.prototype.reset = function() {
this.clear()
this.$hidden.val(this.original.hiddenVal)
this.$preview.html(this.original.preview)
this.$element.find('.fileinput-filename').text('')
if (this.original.exists) this.$element.addClass('fileinput-exists').removeClass('fileinput-new')
else this.$element.addClass('fileinput-new').removeClass('fileinput-exists')
this.$element.trigger('reset.bs.fileinput')
},
Fileinput.prototype.trigger = function(e) {
this.$input.trigger('click')
e.preventDefault()
}
// FILEUPLOAD PLUGIN DEFINITION
// ===========================
var old = $.fn.fileinput
$.fn.fileinput = function (options) {
return this.each(function () {
var $this = $(this),
data = $this.data('bs.fileinput')
if (!data) $this.data('bs.fileinput', (data = new Fileinput(this, options)))
if (typeof options == 'string') data[options]()
})
}
$.fn.fileinput.Constructor = Fileinput
// FILEINPUT NO CONFLICT
// ====================
$.fn.fileinput.noConflict = function () {
$.fn.fileinput = old
return this
}
// FILEUPLOAD DATA-API
// ==================
$(document).on('click.fileinput.data-api', '[data-provides="fileinput"]', function (e) {
var $this = $(this)
if ($this.data('bs.fileinput')) return
$this.fileinput($this.data())
var $target = $(e.target).closest('[data-dismiss="fileinput"],[data-trigger="fileinput"]');
if ($target.length > 0) {
e.preventDefault()
$target.trigger('click.bs.fileinput')
}
});
Now here is my form:
<form id="default_form" onsubmit="return false;" data-method="websites" enctype="multipart/form-data" data-toastr-position="top-right" data-success="Sent! Thank you!" class="validate" novalidate="novalidate">
<input type="hidden" name="{$my_csrf_name}" id="csrf" value="{$my_csrf_value}" />
<input type="text" class="form-control required" value="" name="d[DEF_TITLE]" id="MY_TITLE">
<textarea class="form-control required" rows="3" name="d[MY_DESC]" id="MY_DESC"></textarea>
<div class="fileinput fileinput-new" data-provides="fileinput">
<div class="fileinput-new thumbnail" style="min-width: 160px; min-height: 100px; max-width: 200px; max-height: 150px; line-height: 10px;"> <img src="{$_homeurl}space/perm/img/favicon/{$set_data.MY_FAVICON}" alt="{$homeurl}space/perm/img/favicon/{$set_data.MY_FAVICON}" data-src="{$homeurl}space/perm/img/favicon/{$set_data.MY_FAVICON}" > </div>
<div class="fileinput-preview fileinput-exists thumbnail" style="max-width: 200px; max-height: 150px;"></div>
<div>
<span class="btn btn-default btn-file" class="upload-image">
<span class="fileinput-new">Select Favicon image</span>
<span class="fileinput-exists">Change</span>
<input type="file" id="MY_FAVICON" name="d[MY_FAVICON]"></span>
<a href="#" class="btn btn-default fileinput-exists" data-dismiss="fileinput">Remove</a>
</div>
</div>
<button id="submit_form" data-fid="default_form" class="btn btn-3d btn-primary btn-xlg btn-block margin-top-30" type="submit">
SUBMIT
</button>
</form>
Now upon clicking the "Select Favicon image" here is my js code event:
var csrf_val = $('#csrf').val();
var csfrData = {};
csfrData['csrf_name'] = csrf_val;
sendFile(this.files[0]);
function sendFile(file) {
$(function() {
$.ajaxSetup({
data: csfrData
});
});
$.ajax({
method: 'post',
url: _admin_url + _curr_mod+'/procedure/uload-image',
data: file,
success: function() {
alert('upload is ok!');
},
processData: false
});
}
upon select of image the JavaScript will process to upload the image in PHP controller/model. As I try to look into the Firebug the post has this values:
ÿØÿà�JFIF������ÿÛ��
Then in the response tab found in the CodeIgniter was this (this might be because of the csrf is not included in the post data):
An Error Was Encountered
The action you have requested is not allowed.
and for the php will just use this code (still not sure how will I handle it in php):
$_FILES['file']
I don't know how to upload an image using an uploader (that has preview of the file) and with csrf in CodeIgniter.
The process is this, upon select of image, an ajax will upload it to the server (temporary folder), and will return a new filename (encryption enabled upon upload in php)