I am sending the selected photo to my controller in asp.net core with ajax and javascript. Thanks to the code below:
<form id="form" name="form" style="display:none;" method="post" enctype="multipart/form-data">
<div class="row">
<div class="col-md-12">
<input onchange="uploadFiles('files');" class="form-control" type="file" id="files">
</div>
</div>
</form>
My javascript and ajax codes:
var sliderFotografEkle = "#Url.Action("sliderFotoKayit", "slider")";
function uploadFiles(inputId) {
var input = document.getElementById(inputId);
var files = input.files;
var formData = new FormData();
for (var i = 0; i != files.length; i++) {
formData.append("files", files[i]);
}
$.ajax(
{
url: sliderFotografEkle,
data: formData,
processData: false,
contentType: false,
type: "POST",
success: function (data) {
alert("Files Uploaded!");
}
}
);
}
It only takes formData in the data part. I want to send a second data. It doesn't send. Probably
processData: false,
contentType: false, from what I gave. but if i don't give them it doesn't send the photo this time. Please help me.
this is where the parameters are given in the controller:
[HttpPost]
public async Task<IActionResult> sliderFotoKayit(slider item, List<IFormFile> files)
I already tested your code on ASP.NET Core 3.1 and found no problem uploading one file at a time.
As I understand, you problem is that you cannot choose and send multiple files at once.
For choosing and sending multiple files at once, your html input tag must have a multiple attribute. Otherwise, it only allows you to choose one file at a time.
<input onchange="uploadFiles('files');" class="form-control" type="file" id="files" multiple>
Updated after the author provided more context:
For any additional value you want to send in your form data, just you append(key: string, value: any) method.
Updated JS with an additional int field:
function uploadFiles(inputId) {
var input = document.getElementById(inputId);
var files = input.files;
var formData = new FormData();
for (var i = 0; i != files.length; i++) {
formData.append("files", files[i]);
}
formData.append("id", 3); // append additional int field here
$.ajax(
{
url: sliderFotografEkle,
data: formData,
processData: false,
contentType: false,
type: "POST",
success: function (data) {
alert("Files Uploaded!");
}
}
);
}
</script>
Controller method signature to receive files and an additional int field:
[HttpPost]
public async Task<IActionResult> HandleFileUpload(int id, List<IFormFile> files)
Some more details:
When you send form data to the server, request will have content-type: multipart/form-data;. As one HTTP request can just have one content-type, there are 2 choices:
The easy way: Add new fields to form, either through input fields in html or formData.append(key, value) in js. This is recommended because:
content-type: multipart/form-data; can include both files and any other types that HTML form support.
content-type: multipart/form-data; has built-in support in ASP.NET, so form content will automatically bind to controller method parameters.
The hard way: Serialize formdata into string, then return content-type: application/json;. Do this if you don't have control over the server, usually in cases when you have to conform to the API of another server. This is clearly more flexible, but also more complicated.
You will be able to have the data in the form:
{
"formData": serializedFormData,
"id": id
}
The biggest drawback is that the server then have to manually deserialize the form data.
Related
I am new to jQuery and AJAX and I am trying to upload image to my server using it. I have a simple html page
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="script.js"></script>
<form method="post" enctype="multipart/form-data">
Select image to upload:
<input id="profilePic" name="picture" type="file" size="1" onchange="uploadFile('profilePic');" />
</form>
where script file is
function uploadFile(inputId) {
var fileUpload = $("#" +inputId).get(0);
var files = fileUpload.files;
var formData = new FormData();
formData.append(files[0].name, files[0]);
$.ajax({
url: '/Image/File',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function (result) {
}
});
In my controller named ImageController I have a POST method named File which takes zero arguments:
[HttpPost]
public IActionResult File()
{
var file = Request.Form.Files[0];
if (file != null)
{
//work
}
return null;
}
but everytime I submit an image to form nothing happens and I get code 500: internal server error, failed to load resource. I have placed breakpoints in my code but it never entered the File method. What am I doing wrong? htmlpage and script are located in wwwroot, controller is in Controllers folder.
First, your action should take the image as a param:
// Don't use `File` here. You're hiding the base `File` method.
public IActionResult FileUpload(IFormFile file)
{
// Always check content length
if (file?.ContentLength > 0)
{
//work
}
return null;
}
Then, in your JS, the first param to FormData.append should be data name, not the name of the file. Since the action param is file, the name here should be file as well:
formData.append('file', files[0]);
I want to send an image and a number when the user perform an upload.
My Javascript
form.append('file', $(uploader).get(0).files[0]);
var id= $("#id").val();
form.append("id", id);
$.ajax({
method: 'POST',
url: '/images/send',
data: form,
form: false,
processData: false
});
In my action what should I do?
With this I only receive the image.
[HttpPost]
public string send(IFormFile file) // What argument should I use
{
How do I get the number and file?
}
You can add a new parameter of type int to your action method. The parameter name should match with the formdata item name you are sending (id)
[HttpPost]
public string send(IFormFile file,int id)
{
// to do : return something.
}
You need to have the contentType property on your $.ajax method set to false
This should work.
var form = new FormData();
form.append('file', $('#File').get(0).files[0]);
var id= $("#id").val();
form.append("id", id);
var urlToPost ="/images/send";
$.ajax({
method: 'POST',
url: urlToPost ,
data: form,
processData: false,
contentType: false
}).done(function(result) {
// do something with the result now
console.log(result);
}).fail(function(a, b, c) {
alert("error");
});
If you want to send multiple input values with the file input, i suggest you create a view model and use that as explained in this post.
Also it might be a good idea to keep your form elements inside a form and set it's action value to the url you want to send and read that in your javascript code that hard coding it there.
<form asp-action="send" asp-controller="images" method="post">
<input type="file" name="File" id="File" />
<input type="text" id="id" value="0" />
<input type="submit" />
</form>
Now in your javascript you can read it from the form. For example, if you are wiring up the submit event of the form
$(function () {
$("form").submit(function (e) {
e.preventDefault();
var urlToPost = $(this).attr("action");
//your existing code for ajax call
});
});
In my application, I have one form which is rendering from partial view. From that form I want to send whole form data and selected file of file control. Form submission is using ajax call. To save selected file to folder, code I have is like below :
JavaScript function :
<script type="text/javascript">
$(function () {
$('#careerForm').submit(function (e) {
e.stopPropagation();
e.preventDefault();
var formData = new FormData();
var totalFiles = document.getElementById("fuUploadCV").files.length;
for (var i = 0; i < totalFiles; i++) {
var file = document.getElementById("fuUploadCV").files[i];
formData.append("FileUpload", file);
}
$.ajax({
type: "POST",
url: '/CareerSurface/UploadImage/', //put your controller/action here
data: formData,
dataType: 'json',
contentType: false,
processData: false,
beforeSend: function (xhr) {
//do something before send
},
success: function (data) {
//do something if success
},
error: function (data) {
//do something if error
}
});
});
});
</script>
Html :
using (Html.BeginForm("ApplyNow", "CareerSurface", FormMethod.Post, new { enctype = "multipart/form-data", autocomplete = "off", id ="careerForm" })){
<div class="Field-Label-Box">
<label>First Name:<span> *</span></label>
</div>
<div class="Field-Value-Box">
#Html.TextBoxFor(model => model.FirstName, new { id = "txtFirstName", name = "txtFirstName", required = "required" })
#Html.ValidationMessageFor(model => model.FirstName)
</div>
......
<div class="Field-Label-Box">
<label>Upload CV:<span> *</span></label>
</div>
<div class="Field-Value-Box">
#Html.TextBoxFor(model => model.ResumeUpload, new { type = "file", id = "fuUploadCV", name = "fuUploadCV", required = "required" })</div>
<input type="submit" id="btnSave" value="Submit" name="btnSave" />
}
c# :
[HttpPost]
public void UploadImage()
{
if (Request.Files.Count > 0)
{
dynamic file = Request.Files[0];
//do something with your 'file'
}
}
This works perfect to send only selected file. Now my issue is I want to send all another data(model class object) also to the same controller method. I have tried using json also but getting error of 'Illegal Invocation'.
Please guide me how to pass both to gather to single method? If any query, fill free to ask. Help me I got stuck at this point.
Thanks.
I made a test on your code and the only thing you are missing is adding the other fields to the FormData object you are sending through AJAX. What I mean is to modify your javascript code like this:
var formData = new FormData();
var totalFiles = document.getElementById("fuUploadCV").files.length;
for (var i = 0; i < totalFiles; i++) {
var file = document.getElementById("fuUploadCV").files[i];
formData.append("FileUpload", file);
}
// This is what you are missing: adding the other form fields
var txtFirstName = $("#txtFirstName").val();
formData.append("txtFirstName", txtFirstName);
$.ajax({
(... the rest of your code ...)
You need to append every value of your form you want to send to the server.
Then in the server side, you can access your fields in the following way, also based on your current code:
[HttpPost]
public void UploadImage()
{
if (Request.Files.Count > 0)
{
dynamic file = Request.Files[0];
//do something with your 'file'
// This is the way to access your fields based on your code
string txtFirstName = Request.Form["txtFirstName"];
// do something with your fields
}
}
I hope that helps.
I have a form with files. I would like to perform a server-side validation and only then upload the files (since each file makes the request larger).
Is there slick way to do that doesn't include serializing the form's data and running an ajax?
I'm not looking for something like this:
var formData = $('#form').serializeArray();
$.post(url, formData, function(res){
if(res.isValid)
$('#form').submit();
});
Try something like this (for Client side validation) , onclick of submit button
var file = $('#file_upload').prop("files")[0]; //file_upload is form's id
var name = file.name;
var size = file.size;
var type = file.type;
if (type != 'image/png' && type != 'image/jpeg' )throw {"msg": 'Invalid image type'}
if (size > 1024 * 1024 * 2 )throw {"msg": 'Invalid image size'}
And for AJAX Server Side Validation before upload, you need to send file object via Ajax( ***not recommended, might not work in few old browsers)
try {
var formObj = new FormData($('form')[1]); //File Object
$.ajax({
url: "YOUR URL", // do the SERVER SIDE VALIDATION here
data: formObj,
processData: false,
contentType: false,
dataType:'json',
type: 'POST',
success: function(data){
// Success code
}
});
}catch (e) {
console.log(e.msg);
}
out.html is entry point. submitValidate submits form in iframe (in.html). JavaScript snippet (confirm.html) in response from server passes database record to validateClientSideAndUpload which sets hidden field and submits form in parent window to server. Server moves file to appropriate location and creates association with record speficied by id. Posted as a proof of concept.
out.html
<script>
function submitValidate() {
document.getElementById('validate-frame')
.contentDocument.querySelector('form').submit();
}
function validateClientSideAndUpload(id) {
if(document.getElementById('file').value === '') {
alert('Select file');
return;
}
document.getElementById('record-id').value = id;
var form = document.querySelector('form');
if confirm('Upload file?') {
form.submit();
}
}
</script>
<iframe src="in.html" id="validate-frame"></iframe>
<form>
<input type="file" id="file"/>
<input type="hidden" id="record-id"/>
</form>
<button onclick="submitValidate()">Save</button>
in.html (new/invalid)
<form action="confirm.html">
<label>Name</label>
<input type="text" placeholder="data">
</form>
confirm.html (success)
<script>
window.onload = function() {
parent.validateClientSideAndUpload(/* server generated record id */);
}
</script>
I want to uplod multiple files through ajax but I can't figure out how I can grab the files in PHP. Can anyone help me? Thank you!
Here is the code:
HTML:
<form enctype="multipart/form-data" method="POST">
<input type="file" id="file" multiple="multiple" name="file"/>
</form>
<div id="info"></div>
<div id="preview"></div>
JavaScript:
$(document).ready(function(){
$("#file").change(function(){
var src=$("#file").val();
if(src!="")
{
formdata= new FormData(); // initialize formdata
var numfiles=this.files.length; // number of files
var i, file, progress, size;
for(i=0;i<numfiles;i++)
{
file = this.files[i];
size = this.files[i].size;
name = this.files[i].name;
if (!!file.type.match(/image.*/)) // Verify image file or not
{
if((Math.round(size))<=(1024*1024)) //Limited size 1 MB
{
var reader = new FileReader(); // initialize filereader
reader.readAsDataURL(file); // read image file to display before upload
$("#preview").show();
$('#preview').html("");
reader.onloadend = function(e){
var image = $('<img>').attr('src',e.target.result);
$(image).appendTo('#preview');
};
formdata.append("file[]", file); // adding file to formdata
console.log(formdata);
if(i==(numfiles-1))
{
$("#info").html("wait a moment to complete upload");
$.ajax({
url: _url + "?module=ProductManagement&action=multiplePhotoUpload",
type: "POST",
data: formdata,
processData: false,
contentType: false,
success: function(res){
if(res!="0")
$("#info").html("Successfully Uploaded");
else
$("#info").html("Error in upload. Retry");
}
});
}
}
else
{
$("#info").html(name+"Size limit exceeded");
$("#preview").hide();
return;
}
}
else
{
$("#info").html(name+"Not image file");
$("#preview").hide();
return;
}
}
}
else
{
$("#info").html("Select an image file");
$("#preview").hide();
return;
}
return false;
});
});
And in PHP I get $_POST and $_FILES as an empty array;
Only if I do file_get_contents("php://input"); I get something like
-----------------------------89254151319921744961145854436
Content-Disposition: form-data; name="file[]"; filename="dasha.png"
Content-Type: image/png
PNG
���
IHDR��Ò��¾���gǺ¨��� pHYs��������tIMEÞ/§ýZ�� �IDATxÚìw`EÆgv¯¥B-4 ½Ò»tBU©)"¶+*"( E¥J7ôÞ;Ò¤W©¡&puwçûce³WR¸ èóûrw»³ï}fö
But I can't figure out how to proceed from here.
I am using Jquery 1.3.2 maybe this is the problem?
Thank you!
Sorry about the answer, but I can't add a comment yet.
I would recommend not checking the file type in javascript, it is easily bypassed. I prefer to scrutinise the file in PHP before allowing it to be uploaded to a server.
e.g.
This answer taken from another question (uploaded file type check by PHP), gives you an idea:
https://stackoverflow.com/a/6755263/1720515
<?php
$allowedTypes = array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF);
$detectedType = exif_imagetype($_FILES['fupload']['tmp_name']);
$error = !in_array($detectedType, $allowedTypes);
?>
You can read the documentation on the exif_imagetype() function here.
Could you post your PHP code please? And I will update my answer if I have anything to add.
UPDATE:
NOTE: The 'multiple' attribute (multiple="multiple") cannot be used with an <input type='file' /> field. Multiple <input type='file' /> fields will have to be used in the form, naming each field the same with [] added to the end to make sure that the contents of each field are added to an array, and do not overwrite each other when the form is posted.
e.g.
<form enctype="multipart/form-data" method="POST">
<input type="file" id="file_0" name="img_file[]" />
<input type="file" id="file_1" name="img_file[]" />
<input type="file" id="file_2" name="img_file[]" />
</form>
When the form is submitted, the contents of any <input type='file' /> fields will be added to the PHP $_FILES array. The files can then be referenced using $_FILES['img_file'][*parameter*][*i*], where 'i' is key associated with the file input and 'paramter' is one of a number of parameters associated with each element of the $_FILES array:
e.g.
$_FILES['img_file']['tmp_name'][0] - when the form is submitted a temporary file is created on the server, this element contains the 'tmp_name' that is generated for the file.
$_FILES['img_file']['name'][0] - contains the file name including the file extension.
$_FILES['img_file']['size'][0] - contains the file size.
$_FILES['img_file']['tmp_name'][0] can be used to preview the files before it is permanently uploaded to the server (looking at your code, this is a feature you want to include)
The file must then be moved to its permanent location on the server using PHP's move_uploaded_file() function.
Here is some example code:
<?php
if (!empty($_FILES)) {
foreach ($_FILES['img_file']['tmp_name'] as $file_key => $file_val) {
/*
...perform checks on file here
e.g. Check file size is within your desired limits,
Check file type is an image before proceeding, etc.
*/
$permanent_filename = $_FILES['img_file']['name'][$file_key];
if (#move_uploaded_file($file_val, 'upload_dir/' . $permanent_filename)) {
// Successful upload
} else {
// Catch any errors
}
}
}
?>
Here are some links that may help with your understanding:
http://www.w3schools.com/php/php_file_upload.asp
http://php.net/manual/en/features.file-upload.multiple.php
http://www.sitepoint.com/handle-file-uploads-php/
Plus, some extra reading concerning the theory around securing file upload vulnerabilities:
http://en.wikibooks.org/wiki/Web_Application_Security_Guide/File_upload_vulnerabilities
You can use ajax form upload plugin
That's what i have found couple of days ago and implemented it this way
Ref : LINK
You PHP Code can be like this
uploadimage.php
$response = array();
foreach ($_FILES as $file) {
/* Function for moving file to a location and get it's URL */
$response[] = FileUploader::uploadImage($file);
}
echo json_encode($response);
JS Code
options = {
beforeSend: function()
{
// Do some image loading
},
uploadProgress: function(event, position, total, percentComplete)
{
// Do some upload progresss
},
success: function()
{
// After Success
},
complete: function(response)
{
// Stop Loading
},
error: function()
{
}
};
$("#form").ajaxForm(options);
Now you can call any AJAX and submit your form.
You should consider below code
HTML
<input type="file" name="fileUpload" multiple>
AJAX
first of all you have to get all the files which you choose in "input type file" like this.
var file_data = $('input[type="file"]')[0].files;
var form_data = new FormData();
for(var i=0;i<file_data.length;i++)
{
form_data.append(file_data[i]['name'], file_data[i]);
}
then all your data is in formData object now you can send it to server(php) like this.
$.ajax({
url: 'upload.php', //your php action page name
dataType: 'json',
contentType: false,
processData: false,
data: form_data,
type: 'post',
success: function (result) {
// code you want to execute on success of ajax request
},
error: function (result) {
//code you want to execute on failure of ajax request
}
});
PHP
<?php
foreach($_FILES as $key=>$value)
{
move_uploaded_file($_FILES[$key]['tmp_name'], 'uploads/' .$_FILES[$key]['name']);
}