I am trying to ajax submit form to a Laravel 5 controller method. I understand that in php, you can define a FormData object, append the input fields to the object and send it to the server where you can now extract the values using the input field names.
Like so:
var form_data = new FormData();
formdata.append('file_name', 'some_file_name_from_form.png');
When form_data is sent as the data in the ajax call, I can get the file in PHP by using the $_FILES['file_name']['name'];.
So I tried this same logic in a Laravel controller method. I tried just to grab the name of the file in the $request object but only got null.
My controller method:
public function postImage(Request $request)
{
$file = $request->get('file_name');
dd($file);
}
But when I dd the whole request, I see this weird object:
array:1 [
"file_name" => UploadedFile {#199
-test: false
-originalName: "work-fitness_00255959.png"
-mimeType: "image/png"
-size: 34215
-error: 0
#hashName: null
path: "/tmp"
filename: "phpVodsUg"
basename: "phpVodsUg"
pathname: "/tmp/phpVodsUg"
extension: ""
realPath: "/tmp/phpVodsUg"
aTime: 2017-06-04 12:42:26
mTime: 2017-06-04 12:42:26
cTime: 2017-06-04 12:42:26
inode: 17573243
size: 34215
perms: 0100600
owner: 1000
group: 1000
type: "file"
writable: true
readable: true
executable: false
file: true
dir: false
link: false
}
]
Please how do I get the image sent through FormData() object in Ajax through it's name?
Thanks for any help
You can do this.
// get the `UploadedFile` object
$file = $request->file('file_name');
$file = $request->file_name;
// get the original file name
$filename = $request->file('file_name')->getClientOriginalName();
$filename = $request->file_name->getClientOriginalName();
Check out the documentation for more information https://laravel.com/docs/5.4/requests#retrieving-uploaded-files
The api methods available on the uploaded file http://api.symfony.com/3.0/Symfony/Component/HttpFoundation/File/UploadedFile.html
The code bellow is working for me:
$("#your_form").submit(function(e){
e.preventDefault();
var form = $(this);
var url = form.attr("action");
var data = new FormData(form[0]);
$.ajax({
url: url,
type: 'POST',
data: data,
cache: false,
processData: false,
contentType : false,
success: function (data) {
console.log(data);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR, textStatus, errorThrown);
}
});
});
my problem was in property contentType. So, I set as false and it's ok!
Related
I know, similar questions had been asked before.
All questions I found concerns upload within a form and need a submit button. This I don't want. I want upload to start after file selection is made (I'm aware of security risks).
Why is the contend of the file dictionary not send?
The button itself is created by JS:
downLoadBtn = document.createElement('INPUT');
downLoadBtn.id = 'downloadBtn';
downLoadBtn.type = 'file';
downLoadBtn.onchange = function(){upload()}
function upload(){
file = document.getElementById('downloadBtn')
console.log(file['files']['0'])
$.ajax({
type: "POST",
url: '/upload',
dataType : 'json',
data: JSON.file,
success: function (response){
console.log(response);
}
});
}
python:
#app.route('/upload', methods = ['POST'])
def upload():
if request.method == 'POST':
data = request.files
print(data)
return jsonify(data)
What I'm doing wrong?
You pass JSON.file as the data parameter which is not defined in the code you posted, it should be the file tat was selected.
Since your server side code expects multipart from data, you'll have to use a FormData object.
function upload(){
file = document.getElementById('downloadBtn')
console.log(file['files']['0'])
var fd = new FormData();
fd.append('file', file['files']['0']);
$.ajax({
type: "POST",
url: '/upload',
dataType : 'json',
data: fd,
contentType: false,
processData: false,
success: function (response){
console.log(response);
}
});
}
I have renamed my uploaded file on server, when i try to delete my image through dropzone.js the file does not get deleted because it is renamed.
var myDropzone = new Dropzone("div#dropzoneFileUpload", {
addRemoveLinks: true,
url: baseUrl+"/img/upload/store",
params: {
_token: token,
},
success: function (data, textStatus, XmlHttpRequest){
},
removedfile: function(file) {
var name = file.upload.filename;
jQuery.ajax({
headers: {
'X-CSRF-TOKEN': jQuery('meta[name="_token"]').attr('content')
},
type: 'POST',
url: '{{ url("delete") }}',
data: {filename: name},
success: function (data){
console.log("File has been successfully removed!!");
},
error: function(e) {
console.log(e);
}});
var fileRef;
return (fileRef = file.previewElement) != null ?
fileRef.parentNode.removeChild(file.previewElement) : void 0;
},
});
I propose the following:
In the success method, you should be getting the uploaded file back as the first argument (what you currently have as data) and the second argument would be the new name you send back (what you currently have as textStatus).
With this, you could loop the current files in the Dropzone, finding the the correct file out of the list based on the file you get back as a first argument in the response, and then change its name accordingly. So that when you press delete, it will have the right name
Please consider the following modified pseudo code which assumes you're sending back the new file name from the server.
var myDropzone = new Dropzone("div#dropzoneFileUpload", {
addRemoveLinks: true,
url: baseUrl+"/img/upload/store",
params: {
_token: token,
},
success: function (fileSentToServer, newFileName){
// Access the current files in the list/dropzone
var fileList = myDropzone.files;
// Loop over
fileList.forEach(file => {
//Find the corresponding file in the list you just uploaded
if(file.name == fileSentToServer.name) {
//Rename it
file.name = newFileName
}
})
},
removedfile: function(file) {
// This name should now be the renamed version
var name = file.upload.filename;
jQuery.ajax({...
},
});
It's also possible you may not even need the loop if the file param returned in the success method is a direct reference to the file in the file list.
I'm trying to use mcrypt and encrypt and decrypt json data crossing domain. Actually, this worked when I use the encryption in the same domain, but did not work in ajax.
Here is function all:
function all($contentType = 'page') {
$secret_key = "12345678911234567892123456789312";
$this->load->database();
$query = $this->db->query(
"SELECT * FROM category"
);
$buffer = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $secret_key, json_encode($result), MCRYPT_MODE_ECB);
$this->output->set_output(base64_encode($buffer));
Here is file of view:
$(function(){
try {
$.ajax({
type: "GET",
url: "http://localhost:8888/DIY/index.php/user/all/json",
crossDomain: true,
contentType: "application/x-www-form-urlencoded",
async: false,
dataType: 'text',
processData: false,
cache: false,
success: function (response) {
var a = mcrypt.Decrypt($.base64('decode', response ));
console.log( JSON.parse(a) );
},
error: function (ErrorResponse) {
console.log('error');
}
});
}
catch (error) {
}
});
The output in Chrome is:
[{"id":"1","EMAIL":"sda#q.com","PHONE":"sdsng","USERNAME":"12das","FIRST_NAME":null,"LAST_NAME":null,"PASSWORD":"","TYPE":null},{"id":"2","EMAIL":"adas","PHONE":"dsada","USERNAME":"asdasd","FIRST_NAME":null,"LAST_NAME":null,"PASSWORD":"","TYPE":null}]
And if I add JSON.parse(a) in the view file, it will display nothing. However, after I get console.log(a) in Chrome, I directly copy the output data as the parameters, and use it in Chrome console
JSON.parse('[{"id":"1","EMAIL":"139520519#qq.com","PHONE":"yang_zhang","USERNAME":"122545929","FIRST_NAME":null,"LAST_NAME":null,"PASSWORD":"","TYPE":null},{"id":"2","EMAIL":"adas","PHONE":"dsada","USERNAME":"asdasd","FIRST_NAME":null,"LAST_NAME":null,"PASSWORD":"","TYPE":null}]')
[Object, Object]
The output is what I am looking for!!! Can anyone help me to solve this problem?
Now it is solved. I change the mode of mcrypt from ecb to cfb, and pass the IV to different domain. Then using passed IV to decrypt data will get the string which can use JSON.parse() to get expected json object
I wish to load a json file using extjs. Previously I was loading my json file with the help of jquery library as below:
Ext.define('app.store.Students', {
extend: 'Ext.data.Store',
model: 'app.model.Student',
storeId: 'StudentData',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'data/users.json',
success: function(resp) {
console.log(resp.responseText);
},
reader: {
type: 'json',
root: 'student1',
model: 'app.model.Student',
successProperty: 'success'
}
}
});
But now I want to load my json file using ExtJs. I tried the below code:
Ext.define('app.store.Students', {
extend: 'Ext.data.Store',
model: 'app.model.Student',
storeId: 'StudentData',
autoLoad: true,
});
Ext.Ajax.request({
url: 'data/users.json',
//method: 'GET',
success: function(response){
var text = response.responseText;
alert('1')
console.log(this.url);
// process server response here
}
});
but it says 'Uncaught TypeError: Cannot call method 'indexOf' of undefined'. When inspected in firebug, the url given below is undefined in ext-all-debug.js.
urlAppend : function(url, string) {
if (!Ext.isEmpty(string)) {
return url + (url.indexOf('?') === -1 ? '?' : '&') + string;
}
return url;
},
I tried to console the url as given above in Ext.Ajax.request method, it says url is undefined. Where am I going wrong?
FYI: This is my file structure:
-html file
-data folder - users.json
-app folder - store folder - js file (This is where I use my Ext.Ajax.request method)
Am I going wrong in the relative path? If so, how I should use it?
If data is not specified, and if autoLoad is true or an Object, this store's load method is automatically called after creation.Either set autoLoad to false or use proxy with type ajax and reader and then a callback function to handle your json data.
Update : Try this
Ext.define('app.store.Students', {
extend: 'Ext.data.Store',
model: 'app.model.Student',
storeId: 'StudentData',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'app/data/users.json',
reader:{
type: 'json',
root: 'student1'//If you are using student1 as root.
}
}
I am trying to load a JSON data which is replied back by an AJAX request to a grid.
My store definition:
Ext.define('Report.store.CustomerDataStore', {
extend: 'Ext.data.Store',
requires: [
'Report.model.Customer'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
autoLoad: false,
storeId: 'CustomerDataStore',
model: 'Report.model.Customer',
proxy: {
type: 'ajax',
url: '',
reader: {
type: 'json',
root: 'data',
record: 'fields'
}
}
}, cfg)]);
}
});
There is a button in my app which is defined as follows:
xtype: 'button',
handler: function(button, event) {
var queryform = this.up('form').getForm();
var me = this;
if(queryform.isValid())
{
Ext.Ajax.request({
url: 'customers/', // where you wanna post
success: function(response) {
var mystore = Ext.data.StoreManager.lookup('CustomerDataStore');
var myData = Ext.JSON.decode(response.responseText);
console.log(myData.toSource());
mystore.loadData(myData);
},
jsonData: Ext.JSON.encode(queryform.getValues())
});
}
},
The problem is that my grid doesn't show the replied data! I am sure that my replied JSON format is OK. I have checked it with a json file. also myData.toSource() returns my desired JSON format.
I am pretty confused what I am doing wrong?
Could you plz help?
I found the solution, I had to use loadRawData() function instead of loadData().
loadData() loads models i.e. records, and doesn't parse JSON data inside. You need to specify your JSON format in proxy reader and then store will automatically do Ajax call when you call store.load()