How to upload file via ajax - asp.net-mvc-3

I have file upload which doesn't use form to upload the file instead I want to upload it using ajax. I tried the following approach but I cannot pass the file. It's null. Please help. Below is my implementation.
HTML and jQuery function
<div id="Upload">
<input type="file" accept="application/x-shockwave-flash" id="virtualtourfile" enctype="multipart/form-data"/>
<input type="button" value="Upload" id="btnUpload"/>
</div>
$('#btnUpload').click(function () {
$.ajax({
url: "uploadvideo",
type:'POST',
data: $("#virtualtourfile:file"),
success: function (data) {
}
});
});
Controller
public ActionResult UploadVideo(HttpPostedFileBase file)
{
return Json("", JsonRequestBehavior.AllowGet);
}

There are a couple of options. If the client browser supports the HTML5 File API you could use it to upload a file asynchronously to the server. If you need to support legacy browsers that do not support this API you could use a file upload component such as Uploadify, Fine uploader, jquery form, ... The advantage of those plugins is that they will test the capabilities of the browser and if it supports the File API it will use it, otherwise it will fallback to older techniques such as hidden iframes or Flash movies.

I've used a few plugins and I found the Kendo UI upload plugin nice, here is a link how it works:
http://demos.kendoui.com/web/upload/async.html
and you can find the sample project for Asp.Net MVC 3 here:
http://www.kendoui.com/forums/ui/upload/upoad-with-mvc.aspx
[HttpPost]
public ActionResult Save(IEnumerable<HttpPostedFileBase> attachments)
{
// The Name of the Upload component is "attachments"
foreach (var file in attachments)
{
// Some browsers send file names with full path. This needs to be stripped.
var fileName = Path.GetFileName(file.FileName);
var physicalPath = Path.Combine(Server.MapPath("~/App_Data"), fileName);
file.SaveAs(physicalPath);
}
// Return an empty string to signify success
return Content("");
}

Related

How can I upload files and form data with jQuery?

I would like to upload a file and form data with Jquery. My html;
<form id="kayit" action="" method="post" enctype="multipart/form-data">
<input type="text" name="yazi" />
<input type="file" id="resim" name="resim"/>
<a onclick="kontrolet();" id="yolla">Yolla</a>
</form>
<div id="sonuc"></div>
and my js;
function kontrolet()
{
var veriler = jQuery("#kayit").serialize();
//console.log(veriler);
jQuery.ajax({
type:'POST',
url:'form.php',
data: veriler,
processData: false,
beforeSend: function () {
jQuery("#sonuc").html("Lütfen Bekleyin....");
},
success: function(sonuc)
{
jQuery('#sonuc').html(sonuc);
}
});
}
I have get filename, but this not working. Help ?
You cant upload a file through ajax using simple javascript (one of the reasons is that javascript cannot access the file system at the moment, so it cannot read content to send it on an AJAX request).
For that kind of feature you have to use some plugin that uses action script or java. There are many available online (search ajax file upload), but in my opinion you are better off using an old fashioned POST.
I've used jQuery to upload file in the background using the AjaxUpload plugin - it builds an iFrame in the background, clones your form and submits the clone to that.

AJAX file upload in Play Framework 2.1 RC1 delivers an empty file

Scala/Play gurus out there.
I'm trying to upload a file using AJAX, in Play 2.1 (RC1). For the client part I'm using eldarion/bootstrap-ajax and everything seems to be fine, except that the uploaded file is empty.
The front-end snippet:
...
<form action="#routes.Campaigns.upload" method="post" class="form ajax replaceable" data-replace=".replaceable">
<input type="file" name="picture">
<p><input class="btn" type="submit"></p>
</form>
...
Note that I had to use the explicit <form> tag instead of the #form helper, due to the fact that the required css class (data-replace) contains a dash, and therefore can not be used as a Symbol. But anyway. The called action in the controller looks like this:
def upload = Action(parse.temporaryFile) {
request =>
Logger.info("Trying to upload a file")
val resultString = try {
val file = new File("/tmp/picture")
request.body.moveTo(file, true)
"file has been uploaded"
} catch {
case e: Exception => "an error has occurred while uploading the file"
}
val jsonResponse = Json.toJson(
Map("html" -> Json.toJson("<p>" + resultString + "</p>")
)
)
Ok(jsonResponse)
}
I'm aware that as my development goes forward the file name should be more intelligently set, but for the moment being, /tmp/picture is for me as good a name as any other one.
The JSON response gets generated (with the "file has been uploaded" message within), and is sent back to the browser as the payload of the 200 response. The JSON is received and correctly used to modify the page (in this case, merely removing the very uploading form).
But the file, although appearing in the right moment and in the right place, is always empty:
larsson:tmp bruno$ ls -l /tmp/picture
-rw-r--r-- 1 bruno staff 0 7 Jan 03:07 /tmp/picture
That's specially strange, in my opinion, because the uploading code which uses a traditional multipart/form-data form, with no AJAX whatsoever, and an Action with parse.multipartFormData as a parameter, instead of parse.temporaryFile, works finely.
Any help will be very appreciated. Thanks in advance.
I don't know bootstrap-ajax, anyway if it hasn't dedicated support for uploading files via AJAX (and I didn't find any info about that possibility in its readme file) it will NOT send files with AJAX.
Reason: In standard JavaScript uploading files with AJAX is not possible due the security limits and there are some techniques to workaround this, mainly using iFrames, however I can't see nothing similar in the code of bootstrap-ajax so probably you need to modify it or use other solution.
Solution: There are some AJAX file uploaders, which works good with HTML5 ie. jQuery File Upload, which offers ajax upload, multi-file uploads, drag file to the drop zone etc.
In general HTML5 supports file uploads better than earlier versions of HTML, so you can build uploader easily without need of using additional plugins, take a look to this topic. As you can see it delivers possibilities to validate some data BEFORE the upload and also offers progress bars.
I'm currently trying to implement something like this and I got a first version working. This is how I do it:
In my Controller I define a method for uploading files. In my case I use Action.async since I save stuff to my MongoDB with reactivemongo. I have removed that code so that it do not complicate this example.
What I do in this example is that I upload a csv file, save it to disk and then produce the first row back as a string to the user. In real life the method produces a list back so that user is able to choose which column represent what an so on.
I use mighty csv for csv parsing. GREAT LIB!
Application:
def upload = Action.async(parse.multipartFormData) {
implicit request =>
val result = uploadForm.bindFromRequest().fold(
errorForm => Future(BadRequest(views.html.index(errorForm))),
form => {
import java.io.File
request.body.file("csvFile").map {
csv =>
val path = current.configuration.getString("csv.job.new.file.path").getOrElse("")
val name = DateTime.now().getMillis + ".csv"
csv.ref.moveTo(new File(path + name))
val settings = CSVReaderSettings.Standard(linesToSkip = form.linesToSkip)
val rows: Iterator[Array[String]] = CSVReader(path + name)(settings)
val firstRow = rows.next()
val test = firstRow match {
case xs if xs.size == 0 || xs.size == 1 => xs.mkString
case xs if xs.size > 1 => xs.mkString(", ")
}
Future(Ok(test))
}.getOrElse(Future(BadRequest("ahadasda")))
}
)
result
}
routes:
POST /upload #controllers.Application.upload
I use # before the controllers because I use DI with guice for my service classes.
Since we will use javascript for uploading we need to define our jsRoutes:
jsRoutes:
def javascriptRoutes = Action {
implicit request =>
import routes.javascript._
Ok(
Routes.javascriptRouter("jsRoutes")(
Application.upload
)
).as("text/javascript")
}
Remember to import in your template where you want to use the routes:
<script type="text/javascript" src="#routes.Application.javascriptRoutes"></script>
<script src="#routes.Assets.at("javascripts/app.js")#Messages("js.version")" type="text/javascript" ></script>
In my view template I have a regular helper form. There is some css style stuff I do to
change the looks and feel of the upload button and file chooser. But the input fields
are there.
index.scala.html:
<div class="csvContainer">
#helper.form(action = routes.Application.upload, 'enctype -> "multipart/form-data", 'id -> "csvUpload") {
#Messages("upload.row.skip")
#inputText(uploadForm("linesToSkip"), 'class -> "hidden")
<div style="position:relative;">
<div id="csvFile" style="position:absolute;">
#Messages("upload.choose")
</div>
<input id="uploadFile" type="file" name="csvFile" style="opacity:0; z-index:1;" onchange="document.getElementById('csvFile').innerHTML = this.value;" />
</div>
<p>
<input type="submit" value="#Messages("upload.submit")">
</p>
}
</div>
In app.js is where the ajax magic happens, remember I have not implemented any validation or cool html5 stuff yet as the progressbar and other handlers, described in besiors link.
I use regular JQuery.
app.js:
$('#uploadFile').change(function(){
var name = $(this).val().split("\\");
console.log(name[2]);
$('#csvFile').text(name[2]);
});
$('#csvFile').click(function(){
$('#uploadFile').click();
});
$("#csvUpload").submit(function(e) {
e.preventDefault();
var formData = new FormData();
formData.append('csvFile', $( '#uploadFile' )[0].files[0]);
formData.append('linesToSkip', $( "#linesToSkip").val());
jsRoutes.controllers.Application.upload().ajax({
data: formData,
processData: false,
contentType: false,
cache: false,
type: 'POST',
success: function(data){
alert(data);
}
});
});
I have removed a lot of code to simplify this example and I hope that I have not forgotten anything. Hope this helps!

Uploading Image Using JQuery And Django

Before you continue reading, trust me when I say I have read all the other posts on this subject, and none of them helped.
I am trying to add image upload functionality to my website. I want to upload the image
via an ajax post. I cannot get this working.
Here is what I have:
HTML - i have a special setup so that an image is displayed instead of a stupid button
and the text field. I am also using the onChange event to automatically submit when I have hit "OK" after selecting the image.
<form id="add-picture-form" method="POST" action="/api/upload_image/" enctype="multipart/form-data">{% csrf_token %}
<div class="thumbnails" style="width:400px;">
<label class="cabinet BrandHeader">
<input type="file" class="file" id="upload-photo" onChange="$('#add-picture-form').submit();" />
</label>
</div>
</form>
Jquery:
$('#add-picture-form').submit(function() {
//var filename = $("#upload-photo").val();
var photo = document.getElementById("upload-photo");
var file = photo.files[0];
$.ajax({
type: "POST",
url: "/api/upload_image/",
enctype: 'multipart/form-data',
data: {'file': file.getAsBinary(), 'fname' : file.fileName },
success: function(){
alert( "Data Uploaded: ");
}
});
return false;
});
Finally my django view that is hit when you post to /api/upload_image/
def ajax_upload( request ):
print request.POST
print request.FILES
return http.HttpResponse(simplejson.dumps([True]), mimetype='application/javascript')
I have tried to write the image to binary, but I cannot open that data that has written.
Why is uploading an image using javascript so hard? I am an idiot and just not using a simple solution? If so, please tell me what is the best way to use jQuery to upload an image in Django.
Try the jQuery plugins Uploadify or SWFUpload. Someone even did the Django integration for you, see: https://github.com/tstone/django-uploadify and http://blog.fogtunes.com/2009/11/howto-integrate-swfupload-with-django/.
I'm not that familiar with django but I think the issue is that uploading a file via AJAX isn't as simple as you might think.
There are several methods of getting around this, but I recommend using one that already exists. Since you are using jquery, I would recommend the jquery forms plugin: http://jquery.malsup.com/form/#getting-started
The plugin supports file uploading out of the box, and really all you'll need to do is wire it up to your form:
$('#add-picture-form').ajaxForm();
see also: How can I upload files asynchronously?

use html5 multiple attribute to trigger multiple single uploads

Sorry for the confusing title.
I have a form-- form1 that has one file input ( with multiple attribute set so that user can select mutiple files). The form doesn't get submitted.
I have another form -- form2 that has a single file input . no mutiple attribute.
Now via javascript i would like to fetch each files from the fileinput from the previous form and then assign the file to the form2's input field and then do an ajax submit.
Once the ajax submit is complete I would like to do the same to 2nd file and then 3rd file and so on.
I don't want to use flash or java applet.
I am fully aware that IE doesn't support multiple attribute
opera can use invalid min max attribute to do the same.
My basic question would be how to fetch the files from the form1 input field and then assisgn it to form2's field ..
Is there a solution for this ?
or is my approach itself incorrect ?
What I want to achieve on UI side ?
The file gets uploaded and server does some processing and returns some data.
so what I want is user can select 10 files but as soon as 1st file is uploaded the output is received.
First : My idea is wrong.
We cannot assign a value via javascript to the input with type = file .
I thought of another idea using the XMLHttpRequest.
here is my code :
<form id="new_picture_form" method="post" enctype="multipart/form-data" action="some url" accept-charset="UTF-8">
<input id="original_input" class="file_hidden" type="file" onchange="handleFiles(this.files);" name="picture[image][]" multiple="multiple">
</form>
<form id="fileinfo" method="post" enctype="multipart/form-data" action="some url">
</form>
<script type="text/javascript">
function handleFiles(files)
{
for (var i = 0; i < files.length; i++) {
FileUpload(files[i])
}
}
function FileUpload(file) {
var data = new FormData(document.getElementById("fileinfo"));
var xhr = new XMLHttpRequest();
this.xhr = xhr;
data.append('some field',"that you want to pass as param ")
data.append('type',"picture")
data.append("picture[image]", file);
xhr.open("POST", "URL",true);
xhr.send(data);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
eval(xhr.responseText) // basically the result from server contains some script
}
}
}
</script>

MVC CSV File Download + Project Awesome

I'm currently using project awesome to pop a form which asks for an account number.
I take the number and generate a csv file and send it to the browser:
string billcsv = "account_ref,line1,line2,line3"
var VIRFile = File(new System.Text.UTF8Encoding().GetBytes(billcsv), "text/csv", "billfor" + accnumber+ ".csv")
return Json(VIRFile);
I would like the end user to prompted to save the csv file but cannot figure out who to.
Should I create the CSV file on disk first then pass the url to the file to the success function and use window.open(url) or is it possible to use javascript to recreate the file from the json result?
Json Result:
{"FileContents":[65,99,99,111,117,110,116,95,82,69,70,44,73,78,86,79,73,67,69,95,84,89,80,69,44,73,78,86,79,73,67,69,95,82,69,70,44,81,84,89,95,79,82,68,69,82,44,83,69,82,86,73,67,69,95,84,69,88,84,44,85,78,73,84,95,80,82,73,67,69,44,83,69,82,86,73,67,69,95,65,77,79,85,78,84,13,10,114,114,114,44,73,110,118,111,105,99,101,44,86,73,82,49,48,50,44,49,44,83,116,97,114,83,104,105,112,32,32,79,110,101,13,10,44,76,79,65,32,45,32,32,109,116,114,115,13,10,44,71,82,84,32,45,71,84,44,48,44,48,44,48,13,10,114,114,114,44,73,110,118,111,105,99,101,44,86,73,82,49,48,50,44,50,44,66,111,97,116,32,84,114,97,110,115,102,101,114,115,32,72,105,114,101,32,67,104,97,114,103,101,44,50,53,48,46,48,48,44,53,48,48,46,48,48,13,10,114,114,114,44,73,110,118,111,105,99,101,44,86,73,82,49,48,50,44,51,44,66,101,114,116,104,105,110,103,32,32,82,70,65,32,47,32,77,111,68,44,51,53,48,46,48,48,44,49,48,53,48,46,48,48,13,10],"ContentType":"text/csv","FileDownloadName":"billfor123.csv"}
First of all don't use AJAX for downloading files. Use a normal form submission or an anchor pointing to the controller action which will serve the file. And then in the controller:
public ActionResult Download(string accnumber)
{
string billcsv = "account_ref,line1,line2,line3";
var data = Encoding.UTF8.GetBytes(billcsv);
string filename = "billfor" + accnumber + ".csv";
return File(data, "text/csv", filename);
}
Now in order to invoke this action and have the user be prompted for download simply create a link:
#Html.ActionLink("Download csv", "Download", new { accnumber = "123" })
or if you are using a form:
#Html.BeginForm("Download", "SomeController")
{
#Html.TextBox("accnumber")
<input type="submit" value="Download CSV" />
}
Submitting the form using AJAX has disadvantages. You shouldn't be doing this. I would rather use #Html.BeginForm() helper to generate the form and submit the data using button event.
Hope this helps

Resources