I'm trying to pass my form data as well as data from a file being uploaded
However, I can only manage to pass the form data or file data but not both at the same time.
Here is my javascript for getting the data
var form = document.getElementById('AddDocs');
var data = new FormData(form);
var columns = [];
var values = [];
for (var i = 0; i < files.length; i++) {
data.append(files[i].name, files[i]);
ParseFile(files[i]);
}
var propertyRows = document.getElementsByClassName("docPropertiesTable")(0).rows;
for (var i = 0; i < propertyRows.length - 1; i++) {
//
if (propertyRows(i).cells(1).children(0).value != "") {
//if there is a value
values.push(propertyRows(i).cells(1).children(0).value);
data.append("value" + i, propertyRows(i).cells(1).children(0).value);
//push the dataid of the column on to the array
columns.push(propertyRows(i).cells(1).children(0).name.split("|")[0]);
data.append("columns" + i, propertyRows(i).cells(1).children(0).name.split("|")[0]);
}
}
var jsonText = JSON.stringify({ columns: columns, values:values, data:data });
$.ajax({
type: "POST",
url: "EnterpriseUtilities.aspx/ProcessEnterpriseUpload",
data: jsonText,
contentType: "application/json; charset=utf-8",
dataType: "json",
failure: function () { alert("Uh oh"); }
});
Method 2 for uploading the file
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200 && xhr.responseText) {
alert("upload done!");
} else {
//alert("upload failed!");
}
};
xhr.open('POST', "UploadFile.aspx");
xhr.send(data);
The ajax call is currently getting the form data and then the XMLHTTPRequest is getting the file. I need to make sure the file is uploaded first and then I need to take the data to insert into a database. How can I achieve the upload of the file without losing the form data?
EDIT:
I am trying to get upload the file via XMLHTTP or whatever means necessary. Then I need to get the metadata (form data) that the user enters. Both methods work independently.
My asp.net method for hadling the information is
<WebMethod()> _
Public Shared Function ProcessEnterpriseUpload(columns() As String, values() As String, data As Object) As String
//process information
End Function
I am mainly a desktop developer and am looking for guidance on where to go to get this working.
EDIT 2
Image for context.
http://imgur.com/pizi4yk
Drop file onto table. Fill in file information then when done I need to upload the actual file itself as well as any data the user fills in on the right hand side. There are more fields on the right, but for simplicity I included the top 2.
I figured it out. I upload the file then if that succeeds send the meta data to be processed
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200 && xhr.responseText) {
alert("upload done!");
var jsonText = JSON.stringify({ columns: columns, values:values});
$.ajax({
type: "POST",
url: "EnterpriseUtilities.aspx/ProcessEnterpriseUpload",
data: jsonText,
contentType: "application/json; charset=utf-8",
dataType: "json",
failure: function () { alert("Uh oh"); }
});
} else {
//alert("upload failed!");
}
};
xhr.open('POST', "UploadFile.aspx");
xhr.send(data);
Related
I've got working code in JQuery Ajax, however I've been told I have to use Native JS code to use it, and I'm not very familiar with using native JS for ajax, and most of the internet examples are basic ones. Basically, I have this object:
var Narudzba =
{
SifraNarudzbe: "AAA",
DatumNarudzbe: "",
Osigurano: document.getElementById("checkOsiguranje").value,
BrzaDostava: document.getElementById("checkBrza").value,
KlijentId: document.getElementById("klijentid").value,
Adresa: AdresaVar,
StatusNarudzbeID: 2,
Primaoc: PrimaocVar,
VrijemeIsporuke: null,
CijenaNarudzbe: UkupnaCijena,
NacinPlacanja: parseInt(document.getElementById("NacinPlacanja_Select").value)
};
Which I'm trying to post to my Controller. Here's how my working code in Jquery Ajax looks:
$.ajax({
url: "/klijentarea/klijent/SnimiNarudzbu",
data: Narudzba,
type: 'POST',
success: function (data) {
for (var i = 0; i < stavke_niz.length; i++) {
stavke_niz[i].NarudzbeId = parseInt(data);
}
stavke_niz = JSON.stringify(stavke_niz);
$.ajax({
url: "/klijentarea/klijent/SnimiStavke",
type: "POST",
dataType: "json",
data: stavke_niz,
contentType: 'application/json',
success: function (data) {
if (data === true) {
var id = document.getElementById("klijentid").value;
window.location.href = '/KlijentArea/Klijent?id=' + id;
}
}
});
}
});
Basically, it creates an order (Narudzba) with all sorts of details, posts it to this controller:
[HttpPost]
public int SnimiNarudzbu(Narudzbe Narudzba)
{
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var stringChars = new char[8];
var random = new Random();
for (int i = 0; i < stringChars.Length; i++)
{
stringChars[i] = chars[random.Next(chars.Length)];
}
var finalString = new String(stringChars);
Narudzba.SifraNarudzbe = finalString;
Narudzba.DatumNarudzbe = DateTime.Now;
ctx.Primaoci.Add(Narudzba.Primaoc);
ctx.Naruzbee.Add(Narudzba);
ctx.SaveChanges();
int newid = Narudzba.Id;
return newid;
}
Then I use the returned new ID, and assign it to all the objects inside stavke_niz, which is an array of order listings which gets created elsewhere in the code, and require OrderID before being added to database (I can add that code as well if necessary). Then the array with the updated OrderIDs gets sent to this controller:
[HttpPost]
public string SnimiStavke(IEnumerable<StavkaNarudzbe> stavke_niz)
{
if (stavke_niz != null)
{
ctx.StavkeNarudzbi.AddRange(stavke_niz);
ctx.SaveChanges();
return "true";
}
return "false";
}
Which successfully accepts the JSON posted with AJAX and adds the stuff to the database. Now, when I try to post in Native, like so:
var xhr = new XMLHttpRequest();
xhr.onload = function () {
if (xhr.status === 200 && this.readyState === 4)
{
alert(this.getAllResponseHeaders());
}
};
xhr.open('POST', '/klijentarea/klijent/SnimiNarudzbu', true);
xhr.send(Narudzba);
All of the values inside "Narudzba" are null, despite the object clearly having all the right values before being posted to controller. Help would be greatly appreciated.
You are missing Content-Type setting in your xhr request.
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
This should solve your problem.
Hope this helps!
Trying to save a file to a db. I am using formData via javascript to append the file and adding this as a post object via ajax. for some reason nothing gets sent.
What am I doing wrong?
HTML
<input type="file" style="display: none;" class="btn btn-primary uploadFile">
script:
$(".saveImage")
.on("click",
function() {
var files = $(".uploadFile");
var data = new FormData();
data = $.OverWatch.worker.uploadFileHandler.addUploadFiles(files, data);
$.OverWatch.worker.postUserData("/Administration/AddUserImage", data, function () {
alert("done");
});
});
Functions above look like:
addUploadFiles: function (files, data) {
$.each(files, function (i, v) {
var file = $(this).data("files");
data.append("file", file);
});
return data;
}
postUserData:
postUserData: function(url, data, callback) {
$.LoadingOverlay("show");
$.ajax({
url: url,
type: 'POST',
data: data,
cache: false,
processData: false,
contentType: false,
dataType: "HTML",
success: function(data) {
if (callback) {
callback(data);
$.LoadingOverlay("hide");
}
},
error: function(event, jqxhr, settings, thrownError) {
//$.helpers.errorHandler($("#fileDialogErrors"), event.responseText);
var h;
$.LoadingOverlay("hide");
}
});
},
backend:
public ActionResult AddUserImage()
{
if (Request.Files.Count != 0)
{
//save
}
return null;
}
edit:
var files = $(".uploadFile");
returns:
Your var file = $(this).data("files"); line of code would be returning undefined (unless you have some other javascript adding a data value, but you cannot add files to data so it in any case it would not be returning a file).
Change your loop to
$.each(files, function (i, v) {
for (i = 0; i < v.files.length; i++) {
var file = v.files[i];
data.append("file", file);
}
});
However, you can simplify this by using var data = new FormData($('form').get(0)); which will serialize all you form controls including file inputs to FormData (refer how to append whole set of model to formdata and obtain it in MVC for more information).
I also recommend you change your method signature to
public ActionResult AddUserImage(IEnumerable<HttpPostedFileBase> files)
and let the DefaultModelBinder do its magic.
you can directly get file from controller when called using Request.Files
//(Request) HttpRequestBase object for the current HTTP request
if (Request.Files.Count > 0)//// Is image is uplaod by browse button
{
var inputStream = Request.Files[0].InputStream;
using (var binaryReader = new BinaryReader(inputStream))
{
var ImageBytes = binaryReader .ReadBytes(Request.Files[0].ContentLength); // same as you can get multiple file also
}
var fileExtension = Path.GetExtension(Request.Files[0].FileName);
}
thanks.
I haven't done it with jQuery but just learned how to do it myself yesterday using plain old javascript... the following worked for me. If you want to stick with jquery maybe you can translate the functions to what you need:
var formElement = document.querySelector("form");
var payload = new FormData(formElement);
function onStateChange(ev) {
// Check if the request is finished
if (ev.target.readyState == 4) {
editor.busy(false);
if (ev.target.status == '200') {
// Save was successful, notify the user with a flash
} else {
// Save failed, notify the user with a flash
}
}
};
xhr = new XMLHttpRequest();
xhr.addEventListener('readystatechange', onStateChange);
xhr.open('POST', '/posts');
xhr.send(payload);
Maybe see if using the above code works for you (it just targets a form that you have on the same page), and then you can troubleshoot whether it's your script that's the problem or a backend / communication problem.
I have a method in my controller that submits some changes in the database after receiving a filename that being uploaded to the server. Also this method is getting the fileNameOrigin and fileNameUnique (to be downloaded for saving in the server folder)
public JsonResult Upload()
{
var upload = Request.Files[file];
string fileNameOrigin = System.IO.Path.GetFileName(upload.FileName);
string fileNameUnique = String.Format("{0}_" + fileNameOrigin,
DateTime.Now.ToString("yyyyMMddHHmmss"));
//there is more code that isn't needed in my case
return Json(fileNameOrigin, fileNameUnique);
}
So, here's the question - how to send and receive this data on the client side?
$('#uploadFile').on('change', function (e) {
e.preventDefault();
var files = document.getElementById('uploadFile').files;
if (files.length > 0) {
if (window.FormData !== undefined) {
var data = new FormData();
for (var x = 0; x < files.length; x++) {
data.append("file" + x, files[x]);
}
$.ajax({
type: "POST",
url: '#Url.Action("Upload", "ChatRooms")',
contentType: false,
processData: false,
data: data,
success: onSuccess, //here I need to receive data and do smth with it
error: onError
});
}
}
});
Create a anonymous object with the properties that are required and then pass that single object to the JSON method like:
var data = new {
FileNameOrigin = fileNameOrigin,
FileNameUnique = fileNameUnique
};
return Json(data);
In success callback of ajax, you can access it, for just to check it is working log it on console to see what server has returned like:
success: function(data) {
console.log(data);
},
you might also need to specify datatype in ajax call to json which dictates that JSON is expected from server to be returned in response to this ajax call:
dataType: "json"
Hope it helps!
I am currently trying to solve a problem.
I have several forms on a single page which get sent to the backend asynchronously via ajax.
Now some of them need to have a fileupload which doesnt break the process, so it alsoneeds to be handled asynchronously.
I am trying to figure it out like that :
// Allgemein Submit
$allgSubmit.click(function(){
event.preventDefault();
var gehrKundennummer = $('#gehrKundennummer').val();
var kundenklasse = $("input[type='radio'][name='kundenklasse']:checked").val();
var lkw12t = $('#lkw12t').val();
var lkw3t = $('#lkw3t').val();
var autobus = $('#autobus').val();
var firmenname1 = $('#firmenname1').val();
var firmenname2 = $('#firmenname2').val();
var uidnummer = $('#uidnummer').val();
var peselregon = $('#peselregon').val();
var firmenart = $('#firmenart option:selected').val();
var strasse = $('#strasse').val();
var ort = $('#ort').val();
var plz = $('#plz').val();
var land = $('#land').val();
var fd = new FormData();
var file = fd.append('file', $('#allg_firmen_dok').get(0).files[0]);
var allgArray = {
'gehrKundennummer':gehrKundennummer,
'kundenklasse':kundenklasse,
'lkw12t':lkw12t,
'lkw3t':lkw3t,
'autobus':autobus,
'firmenname1':firmenname1,
'firmenname2':firmenname2,
'uidnummer':uidnummer,
'peselregon':peselregon,
'firmenart':firmenart,
'strasse':strasse,
'ort':ort,
'plz':plz,
'land':land,
'file':file
};
//var data = new FormData();
//jQuery.each(jQuery('#allg_firmen_dok')[0].files, function(i, file) {
// data.append('file-'+i, file);
//});
console.log(allgArray);
$.ajax({
url: "PATHTOFILE/logic/logic_update_client_allg.php",
type: "POST",
data: allgArray,
processData: false, // tell jQuery not to process the data
contentType: false,
success: function(allgArray){
alert(allgArray);
var allgSave = $('#allgSave');
allgSave.text('Aktualisieren erfolgreich!');
allgSave.toggle();
},
error: function(){
var allgSave = $('#allgSave');
allgSave.text('Aktualisieren fehlgeschlagen!');
allgSave.toggle();
}
});
});
The console log of the array returns all values correctly except the one for "file"
it says undefined.
I don't know how to deal with it, are there any requirements that im missing?
Thanks for any kind of help
EDIT
var file = fd.append('file', $('#allg_firmen_dok').get(0).files[0]);
returns undefined
I think the variable fd = new FormData() is an Object and it has attribute "file". So it cannot pass the attribute "file" to another Object "allgArray"
You need to check about it before you call function
$.ajax({
url: "PATHTOFILE/logic/logic_update_client_allg.php",
type: "POST",
data: allgArray,
Think about the data you send! It maybe another instance to get data from "file" of "fd". Hope it help you! ^^
Btw, I used AJAX to send file last time
$(document).ready(function (e) {
$("#Form").on('submit',(function(e) {
e.preventDefault();
$.ajax({
url: "uploader.php", // Url to which the request is send
type: "POST", // Type of request to be send, called as method
data: new FormData(this), // Data sent to server, a set of key/value pairs (i.e. form fields and values)
contentType: false, // The content type used when sending data to the server.
cache: false, // To unable request pages to be cached
processData:false, // To send DOMDocument or non processed data file it is set to false
success: function(data) // A function to be called if request succeeds
{
console.log(data);
}
});
}));
});
add headers: { "Content-Type": "multipart/form-data" } in ajax option
What I am attempting to accomplish here is to create a separate ajax request for each file being uploaded. I have an ajax call that creates a record and returns some html and the tempID of a record that is used by an ajax call which executes on success of the first call. This process appears to be functioning correctly. Where the problem is arising is the loop through the filesList. Before the ajax calls the loop appears to be working fine, but during the ajax call when I'm expecting the files list to increment to the next file in the array it is sending the first file again.
If I only select a single file then everything works correctly. It is as if the ajax calls do not see that the variable "file" is being reset at the beginning of the loop when there are multiple files....got me stumped...
/* Fire the ajax requests when the input files array changes
--------------------------------------------------------------------------*/
$('#theFile').on('change', function()
{
var len = this.files.length;
for(var i = 0; i < len; i++)
{
var file = this.files[i];
// console.log(file.name); This shows the correct file name
var formData = new FormData();
formData.append("file_" + i, file);
$.ajax(
{
url: '/controllerName/buildImageLoadingDIVS',
type: 'POST',
dataType:'json',
data: 'fileName=' + file.name,
success: function(data1)
{
$('#theImages').append(data1.content);
formData.append("tempID", data1.tempID);
// console.log(file.name);
// This shows the first filename in the array as if
// variable "file" was never set to new filelist
$.ajax(
{
url: '/controllerName/the_image_upload',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(data2)
{
$('#temp_wrapper_' + data1.tempID).html(data2);
}
});
}
});
}
You are facing closure problem. As all the success callback are sharing the same closure, so if any success callback is getting executed after the loop ends (which will be in most of the cases) all the success callback is sharing the same file value. Solution of this is creating a closure with IIFE.
Here is the modified code :
//dummy file array
var fileArray = ['file1', 'file2', 'file3']
var len = fileArray.length;
for(var i = 0; i < len; i++)
{
var file = fileArray[i];
console.log(file);
var formData = new FormData();
formData.append("file_" + i, file);
(function(params){
var file = params.file;
var formData = params.formData;
$.ajax(
{
//used this url for testing purpose, replace it with yours
url: 'http://fiddle.jshell.net',
type: 'get',
//change the datatype in your implementation
dataType:'html',
data: 'fileName=' + file,
success: function(data1)
{
//$('#theImages').append(data1.content);
formData.append("tempID", data1.tempID);
console.log("file name in success " + file);
$.ajax(
{
url: 'http://fiddle.jshell.net',
type: 'get',
data: formData,
processData: false,
contentType: false,
success: function(data2)
{
console.log("success");
}
});
},
error : function(){
console.log("error");
}
});
})({
'formData' : formData,
'file' : file
});
}
You can find the fiddle here