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]);
Related
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.
Is there a way to open the OpenFileDialog using js then grab the selected file using only a submit button (without using a form)
this is what i have so far.
#using (Html.BeginForm("UploadAttachment", "DMS", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="attach" />
<button class="btn btn-danger" type="submit" name="attach">Upload</button>
}
Controller:
public async Task<ActionResult> UploadAttachment(HttpPostedFileBase attach)
{
// file processing
}
I'm interpreting your question a little.. I will make two assumptions:
1) you want to upload a file without posting a form and so refreshing the page ie asynchronous upload
2) you want to be able to launch the picker with any button you like (so you can style it how you want to)
The solution below will launch a file picker when a button is clicked. Multiple files can be selected and they will be posted to the server asynchronously (AJAX).
<input type="file" name="attach" id="attach-input" multiple="" style="display:none" />
<button type="submit" name="attach" id="attach-button">Upload</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
var button = $('#attach-button');
var input = $('#attach-input');
// translates collection of files into a form
function BuildFormData(files) {
var data = new FormData();
for (var i = 0; i < files.length; i++) {
data.append(files[i].name, files[i]);
}
return data;
}
// posts the files to a given url
function PostData(url, data) {
$.ajax({
// method
type: 'POST',
// endpoint
url: url,
// next 2 lines required for using FormData with jQuery
contentType: false,
processData: false,
// FormData instance
data: data,
// success handler
success: function (result) {
alert('files uploaded successfully');
console.log(result);
}
});
}
// when the button is clicked..
button.on('click', function (e) {
// it launches the file picker
input.click();
});
// when the file picker changes..
input.on('change', function (e) {
// turn it into a form
var data = BuildFormData(e.target.files);
// post the form to the action method
PostData('/Index/Attach', data);
});
</script>
The action method I used in the asp.net MVC controller will save the files to the App_Data folder of the application:
[HttpPost]
public void Attach()
{
foreach (string file in Request.Files)
{
HttpPostedFileBase fileContent = Request.Files[file];
Stream stream = fileContent.InputStream;
string fileName = Path.GetFileName(file);
string path = Path.Combine(Server.MapPath("~/App_Data"), fileName);
using(var fileStream = System.IO.File.Create(path))
{
stream.CopyTo(fileStream);
}
}
}
Hope that steers you in the right direction.
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']);
}
I am trying to upload a zip file on server unzip it there and return names of file to client.
Code:
<form id="frmUpload" action="UploadHandler.ashx" method="post">
<input id="fileUpload" name="fileToUpload" type="file" accept=".zip"/>
<input id="btnUpload" type="submit" value="Submit" />
</form>
Server Code:
public void ProcessRequest (HttpContext context)
{
var uploadedFile=context.Request.Files["fileToUpload"];
//uploadedFile is then unzipped, filenames are extracted and put in a string
// filenames="a,b,c";
context.Response.Write(filenames);
}
I want to have a callback function at client where I can access this.
I tried a second approach:
$("#frmUpload").submit(function (evt) {
// evt.preventDefault();
//var data = $("#frmUpload")[0].serialize(); // returning empty string
var form = $("#frmUpload")[0];
var file = form["fileToUpload"].value;
$.ajax({
type: "POST",
url: "UploadHandler.ashx",
data: "file="+file,
success: function (result, status, respObj) {
alert(result);
}
});
})
In this case success callback is getting executed however, at server i don't have file object as the data passed to server is only the path of zip file. How can I pass file object to server?
Thanks
You cannot pass the file object to the server. Instead, you should upload the file to the server and then the server unzips the file and sets a flag in session or database indicating that file has been processed.
Meanwhile you can loop an ajax request to the server requesting for file status.
Something like this
var i=0;
for(;;){
if(i==1) return;
$.ajax({
type: "POST",
url: "UploadHandler.ashx",
data: "file="+file,
success: function (result, status, respObj) {
if(result){
alert(result);
i = 1;
}
}
});
}
In a post Yahoo, when attaching files, there is a button "Attach more files" when you press it, it becomes one field to insert the file.
Here is the code:
<a href = "javascript: addUploadFields ();" id = "attach_more"> Attach more files </ a>
How can i implement it MVC?
For uploading multiple files using File Upload control i use JQuery Multifile plugin which is simple and easy to see. See this link JQuery Multiple File Upload
Just inlcude this library and JQuery and its syntax is like
<input type="file" class="multi"/>
Create a Controller and Action that allows you to upload files
Find a client side plugin that achieves uploading multiple files. One that I've found to work quite well is the Upload plugin by Kendo UI
If you go with Kendo UI, this should get you started:
http://docs.kendoui.com/getting-started/using-kendo-with/aspnet-mvc/helpers/upload/overview
Controller:
[HttpPost]
public ActionResult Save(HttpPostedFileBase[] files) {
// The Name of the Upload component is "attachments"
foreach (var file in files) {
//Do Something
}
// Return an empty string to signify success
return Content("");
}
View
<form action="/Controller/Action" method="post" enctype="multipart/form-data">
<input type="file" name="files[]" id="file" />
...
</form>
It is almost same question like https://stackoverflow.com/questions/14575787/ . Plug in support multi file upload. Do let me know if more details are needed.
You can use many file uploader such as
this
and u can use this code for upload
this code is client side:
<form enctype="multipart/form-data">
<input name="file" type="file" />
<input type="button" value="Upload" />
</form>
<progress></progress>
First you can do some validation if you want. For example in the onChange event of the file.
$(':file').change(function(){
var file = this.files[0];
name = file.name;
size = file.size;
type = file.type;
//your validation
});
$(':button').click(function(){
var formData = new FormData($('form')[0]);
$.ajax({
url: 'url', //server script to process data
type: 'POST',
xhr: function() { // custom xhr
myXhr = $.ajaxSettings.xhr();
if(myXhr.upload){ // check if upload property exists
myXhr.upload.addEventListener('progress',progressHandlingFunction, false); // for handling the progress of the upload
}
return myXhr;
},
//Ajax events
beforeSend: beforeSendHandler,
success: completeHandler,
error: errorHandler,
// Form data
data: formData,
//Options to tell JQuery not to process data or worry about content-type
cache: false,
contentType: false,
processData: false
});
});
function progressHandlingFunction(e){
if(e.lengthComputable){
$('progress').attr({value:e.loaded,max:e.total});
}
}
and this is your contoller
[HttpPost]
public ActionResult Save(HttpPostedFileBase[] files) {
// The Name of the Upload component is "attachments"
foreach (var file in files) {
//Do Something
}
// Return an empty string to signify success
return Content("");
}
so if you dont want use ajax use this
#{
ViewBag.Title = "Upload";
}
<h2>
Upload</h2>
#using (Html.BeginForm(actionName: "Upload", controllerName: "User",
method: FormMethod.Post,
htmlAttributes: new { enctype = "multipart/form-data" }))
{
<text>Upload a photo:</text> <input type="file" name="files" multiple />
<input type="submit" value="Upload" />
}
After tyring many unsuccessful solution I got it from
http://lbrtdotnet.wordpress.com/2011/09/02/asp-net-mvc-multiple-file-uploads-using-uploadify-and-jqueryui-progressbar/
click this useful link
I kept the Url Values in a session
public JsonResult Upload(HttpPostedFileBase file)
{
if (Session["myAL"] == null)
{
al = new ArrayList();
}
else
al = (ArrayList)Session["myAL"];
var uploadFile = file;
if (uploadFile != null && uploadFile.ContentLength > 0)
{
string filePath = Path.Combine(HttpContext.Server.MapPath("~/Content/Uploads"),
Path.GetFileName(uploadFile.FileName));
al.Add(filePath);
Session["myAL"] = al;
uploadFile.SaveAs(filePath);
}
var percentage = default(float);
if (_totalCount > 0)
{
_uploadCount += 1;
percentage = (_uploadCount / _totalCount) * 100;
}
return Json(new
{
Percentage = percentage
});
}
and then retrieved them in my Post Create Action
public ActionResult MultimediaCreate(MultimediaModel newMultimedia)
{
if (ModelState.IsValid)
{
db.submitMultimedia(newMultimedia);
al = (ArrayList)Session["myAL"];
foreach(string am in al)
{
MarjaaEntities me = new MarjaaEntities();
MultimediaFile file = new MultimediaFile();
file.MultmediaId = newMultimedia.id;
file.MultimediaFileUrl = am;
me.MultimediaFiles.AddObject(file);
me.SaveChanges();
Session.Remove("myAL");
}
return RedirectToAction("MultimediaIndex");
}
return View();
}