Django File Upload Ajax - ajax

I am trying to upload a file in Django using Ajax. I have tried different approaches but I've get same results. The file cannot be read in the view.
Here is my codes:
#JS
$("#upload-file").click(function() {
var data = new FormData($('#fileForm').get(0));
var csrftoken = getCookie('csrftoken');
$.ajax({
type: "POST",
headers: {'X-CSRFToken': csrftoken},
url: "/countwords/",
data: data,
cache: false,
processData: false,
contentType: false,
success: function(json) {
var ss = json.len;
alert(ss);},
error: function() {
alert('error');}
});
});
finally here is my view codes:
if request.method == 'POST':
print request.FILES.keys()
print request.FILES
print request.POST.keys()
But I get following output when the code is run:
[]
MultiValueDict: {}
[]

Related

JS/JSON file upload immutable dictionary is empty

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);
}
});
}

Passing parameter to MVC Action via Ajax always null

I looked at related questions to to form my ajax request but I can't figure out why this isn't working as the param is always null in the acion
I've done a console.log to check that item in 'data: { data: item }' has a value
//action
public async Task<IActionResult> DeleteMedia(string data)
{
$("#mediaTable").on('click', 'td:nth-child(7)', function () {
var item = $(this).parent().attr("id");
$("#MediaToDownload").val(item);
$.ajax({
url: '#Url.Action("DeleteMedia", "Home")',
type: 'get',
cache: false,
processData: false,
contentType: false,
data: { data: item },
success: function (data) {
location.href = data;
}
});
});
You need to send just the string, as JSON:
data: JSON.stringify(item)

Modify xml using AJAX

I have the following xml file:
<User>
<Address>123</Address>
<FirstName>John</FirstName>
<SecondName>Smith</FirstName>
</User>
I am trying to get it changed with an AJAX call:
var addressid= = 123;
$.ajax({
type: "GET",
url: url,
headers: {
"Authorization": "Basic " + btoa("username:password"),
},
contentType: "application/xml",
dataType: "xml",
async: true,
crossDomain: true,
success: function(xmlResponse) {
alert("Your user has been edited");
$(xmlResponse).find('User').each(function(){
if($(this).find('Address').text() == addressid) {
$(this).find('FirstName').text("Jenifer");
$(this).find('SecondName').text(secondName);
}
});
}
});
An alert comes, this does not display any errors, but it doesn't get passed on to the system. Which means, if I fetch the data from the server, the old name gets displayed. What am I doing wrong?

django ajax MultiValueDictKeyError

I am receiving this error:
MultiValueDictKeyError at /orders/ajax/add_order_line
"'cart'"
Here is my script
var cart = {
0: {
id: "1",
quantity: 50
}
}
$.ajax({
url: myURL,
type: "post",
data: {cart: cart},
success: function() {},
error: function(){}
});
Meanwhile in my django views, the error was found in this line:
def something(request):
cart = request.POST['cart']
Use get method of multivaluedict
request.POST.get('cart')
Your data is a nested array, so you can't send it using the default default application/x-www-form-urlencoded content type.
You can send the data as json:
$.ajax({
url: myURL,
type: "post",
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({cart: cart}),
success: function() {},
error: function(){}
});
Then in your view, you have to load the json string from request.body instead of using request.POST (which is for form-encoded data only).
import json
def my_view(reqest):
data = json.loads(request.body.decode('utf-8'))
cart = data.get('cart')

Laravel 5.4 not able to parse FormData javascript object sent using Jquery Ajax

Lately I've been trying to solve an issue with no luck, basically I'm trying to submit a form to the server using AJAX, the form has files, so I'm using the FormData javascript object in JQuery 1.12. The data arrives to the server but in I way I don't know how to format it.
This is my AJAX function:
function saveMenu(id){
var formElement = document.getElementById("menu-form");
var formData = new FormData(formElement);
formData.append('_method', 'PUT');
$( "#form-wrapper" ).toggleClass( "be-loading-active" );
$.ajax({
type: 'PUT',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
url: "{{url('myUrl')}}",
data: formData,
enctype: 'multipart/form-data',
processData: false,
success: function(response) {
toastr.success('Yai! Saved successfully!')
},
error: function(response) {
toastr.error('Oh oh! Something went really wrong!')
},
complete: function() {
$( "#form-wrapper" ).toggleClass( "be-loading-active" )
}
});
}
and when I perform a dd($request->all()); in my controller I get something like this:
array:1 [
"------WebKitFormBoundaryRCIAg1VylATQGx46\r\nContent-Disposition:_form-data;_name" => """
"_token"\r\n
\r\n
jtv4bnn8WQnP3eqmKZV3xWka2YOpnNc1pgrIfk0D\r\n
------WebKitFormBoundaryRCIAg1VylATQGx46\r\n
Content-Disposition: form-data; name="blocks[43][title]"\r\n
\r\n
...
Things I've tried:
Set the HTTP verb to POST. Same result.
Set the AJAX contentType: false, contentType: application/json. Empty response.
Remove enctype: 'multipart/form-data'. Same response.
Any help is appreciated.
This fixed it for me
data: form_data,
contentType: false,
processData: false,
processData: false prevents jQuery from parsing the data and throwing an Illegal Invocation error. JQuery does this when it encounters a file in the form and can not convert it to string (serialize it).
contentType: false prevents ajax sending the content type header. The content type header make Laravel handel the FormData Object as some serialized string.
setting both to false made it work for me.
I hope this helps.
$('#my-form').submit(function(e) {
e.preventDefault();
var api_token = $('meta[name="api-token"]').attr('content');
form_data = new FormData(this);
$.ajax({
type: 'POST',
url: '/api/v1/item/add',
headers: {
Authorization: 'Bearer ' + api_token
},
data: form_data,
contentType: false,
processData: false,
success: function(result,status,xhr) {
console.log(result);
},
error: function(xhr, status, error) {
console.log(xhr.responseText);
}
});
});
also remember to use $request->all(); $request->input() excludes the files
I've been trying to debug that for 2 hours and i found out that method PUT is not working with formData properly.
Try changing
type : "PUT"
into
method : "POST"
Then change your method on your backend from put to post and you'll see the difference.
I used below codes to test it
$("#menu-form").submit(function (){
var fd = new FormData();
fd.append('section', 'general');
fd.append('action', 'previewImg');
fd.append('new_image', $('.new_image')[0].files[0]);
$.ajax({
method : 'POST',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token()}}'
},
url: "{{url('upload-now')}}",
data : fd,
contentType: false,
processData: false,
success: function(response) {
console.log(response);
},
});
return false;
});
And in my controller
public function test(Request $request){
dd($request->all());
}
Ill try to research more about this issue.
Laravel 7,
if use method PUT in ajax, you can follow
1. change method method: 'PUT' to method: 'POST'
2. add formdata.append with _method PUT like this example :
$('#updateBtn').click(function(e){
e.preventDefault();
var frm = $('#tambahForm');
frm.trigger("reset");
$('.edit_errorNama_kategori').hide();
$('.edit_errorGambar').hide();
var url = "/pengurus/category/"+$('#edit_id').val();
var formdata = new FormData($("#editForm")[0]);
formdata.append('_method', 'PUT'); //*** here
$.ajax({
method :'POST', //*** here
url : url,
data : formdata,
dataType : 'json',
processData: false,
contentType: false,
success:function(data){
if (data.errors) {
if (data.errors.nama_kategori) {
$('.edit_errorNama_kategori').show();
$('.edit_errorNama_kategori').text(data.errors.nama_kategori);
}
if (data.errors.gambar){
$('.edit_errorGambar').show();
$('.edit_errorGambar').text(data.errors.gambar);
}
}else {
frm.trigger('reset');
$('#editModal').modal('hide');
swal('Success!','Data Updated Successfully','success');
table.ajax.reload(null,false);
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert('Please Reload to read Ajax');
console.log("ERROR : ", e);
}
});
});
its works for me
Finally I gave up trying to make it work and tried a more vanilla approach, I still don't know the reason why the request is formated like that, but the XMLHttpRequest() function works perfectly and the migration is not a big deal.
The equivalent of the function I posted about would be:
function saveMenu(action){
var formElement = document.getElementById("menu-form");
var formData = new FormData(formElement);
formData.append('_token', $('meta[name="csrf-token"]').attr('content'));
var request = new XMLHttpRequest();
request.open("POST", "{{url('myUrl')}}");
request.send(formData);
request.onload = function(oEvent) {
    if (request.status == 200) {
      toastr.success('Yai! Saved successfully!');
    } else {
      toastr.error('Oh oh! Something went really wrong!');
}
$( "#form-wrapper" ).toggleClass( "be-loading-active" );
  };
}
Bit late, but;
This will solve your problem;
var formData = new FormData(document.getElementById('form'));
console.log(...formData);
var object = {};
formData.forEach(function (value, key) {
object[key] = value;
});
Then you can send this object to the server. This is much more readable and works great.
OR
You can simply send this directly;
JSON.stringify(Object.fromEntries(formData));
This is the newer approach.
And don't give up :-)

Resources