I want to post a file to server asynchronously without posting the form. I have the following code:
var fileInput = document.getElementById('FileInput');
var file = fileInput.files[0];
var formData = new FormData();
formData.append('file', file, file.name);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://servername/controllername/AnalyseFile', true);
xhr.setRequestHeader('Content-Type', 'multipart/form-data');
xhr.send(formData);
However, when the method is executed on the server, the post body contains no files. The following is from ASP.NET MVC4:
[HttpPost]
public JsonResult AnalyseFile()
{
int filesCount = Request.Files.Count;
if(filesCount == 0) { throw new Exception('no files...'); }
// do stuff
}
The Files collection contains no files and I can't figure out why. Any help appreciated.
In the View, you can do:
<form>
<input name="input1" id="input1"/>
<input name="input2" id="input2"/>
<input name="input3" id="input3"/>
...
<input id="SelectedFile" name="SelectedFile" type="file"/>
</form>
And Javascript:
function AttLogic(_url, _data, _callback) {
$.ajax({
url: _url,
type: 'POST',
xhr: function () {
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) { }
return myXhr;
},
data: _data,
cache: !1,
success: _callback,
contentType: !1,
processData: !1
});
}
function FormDataCustom(f) {
var __frm = jQuery(f), data = new FormData(f);
$(':disabled[name]', __frm).each(function () {
data.append(this.name, $(this).val());
});
return data;
}
function SaveLogic(){
var dt = FormDataCustom(document.forms[0]);
AttLogic(yourUrl, dt, function (r) {
//do something here
});
}
In the Controller:
public ActionResult Save(parameter1,parameter1,..., List<HttpPostedFileBase> SelectedFile)
{
//do something here
}
You will need to read the MultiPartFormData from the Request.
As per this post:
Your method will look something like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace Some.Namespace
{
public class SomeController : ApiController
{
[HttpPost]
public async Task<JsonResult> AnalyseFile()
{
if (!Request.Content.IsMimeMultipartContent())
{
//If not throw an error
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
MultipartFormDataStreamProvider streamProvider = new MultipartFormDataStreamProvider("c:\\tmp\\uploads");
// Read the MIME multipart content using the stream provider we just created.
IEnumerable<HttpContent> bodyparts = await Request.Content.ReadAsMultipartAsync(streamProvider);
// Get a dictionary of local file names from stream provider.
// The filename parameters provided in Content-Disposition header fields are the keys.
// The local file names where the files are stored are the values.
//depending on your version of .net, this might have been changed to FileData instead.
// see: https://msdn.microsoft.com/en-us/library/system.net.http.multipartformdatastreamprovider(v=vs.118).aspx
IDictionary<string, string> bodyPartFileNames = streamProvider.BodyPartFileNames;
//rest of code here
}
}
I haven't tested the above code, but it should point you in the right direction.
Also have a look at How To Accept a File POST
For a more recent article: https://code.msdn.microsoft.com/AngularJS-with-Web-API-22f62a6e
Related
My problem is:
I am uploading a excel file first. After reading the file and manipulating the data, i need to generate a csv and export the same on click of the submit button.
Below is my html/javascript code:
<div>Please upload the Excel File</div>
<form method="POST" id="fileUploadForm" enctype="multipart/form-data">
<input type="file" name="file" /><br/><br/>
<input type="submit" value="Submit" id = "defaultSubmit" />
</form>
Below is the Ajax Request:
$(document).ready(function() {
$("#defaultSubmit").click(function (event) {
//stop submit the form, we will post it manually.
event.preventDefault();
// $("#fileupload").click();
// Get form
var form = $('#fileUploadForm')[0];
// Create an FormData object
var data = new FormData(form);
$.ajax({
url : "/uploadExcelFiles",
type: "POST",
enctype: 'multipart/form-data',
data: data,
processData: false,
contentType: false,
success : function(data) {
},
error : function(data) {
}
});
return false;
});
Now Below is the java code:
#RequestMapping("/uploadExcelFiles")
public void readExcelFile(HttpServletResponse response, #RequestParam("file") MultipartFile uploadedFile) {
File file = new File(uploadedFile.getOriginalFilename());
List<EmployeeData> empData = new ArrayList<>();
empData = blAttendanceService.readFile(file);
TreeMap<Object, Object> map = blAttendanceService.calculateWorkingSecondsForEmployeeInDay(empData);
List<EmployeeChartsModel> list = new LinkedList<>();
for (Entry<Object, Object> ent : map.entrySet()) {
EmployeeChartsModel ehd = new EmployeeChartsModel();
long seconds = (long) ent.getValue();
double dailyHoursSpent = (double)seconds/3600;
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-YYYY");
System.out.println("Date::: " + sdf.format((Date)ent.getKey()) + " ::::::Hours:::: " + dailyHoursSpent);
ehd.setEmployeeDate(sdf.format((Date)ent.getKey()));
ehd.setDailyHoursSpent(dailyHoursSpent);
list.add(ehd);
}
String filename = "DailyAttendanceRecord.csv";
response.setContentType("text/csv");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + filename + "\"");
try {
StatefulBeanToCsv<EmployeeChartsModel> writer = new StatefulBeanToCsvBuilder<EmployeeChartsModel>(response.getWriter())
.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
.withSeparator(CSVWriter.DEFAULT_SEPARATOR)
.withOrderedResults(false)
.build();
writer.write(list);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
EmployeeChartsModel is a class for csv Model.
I am not getting any error in the code. Just the file is not exported. Also, If i read the file manually from my location and direct hit the url of this method, the file is successfully exported. But i am unable to do so through ajax post request.
Kindly suggest the changes so as to export the csv file using this ajax post request.
I am using Java, Spring Boot, Html, Javascript in my code.
I have been searching online looking for the answer to this problem but I cannot seem to find anything that works, I have the following Controller code:
[HttpPost]
public ActionResult UploadFiles()
{
// If files exist
if (Request.Files != null && Request.Files.Count > 0)
{
// ** Do stuff
return Json(new { result = true, responseText = "File(s) uploaded successfully" });
}
// Return no files selected
return Json(new { result = false, responseText = "No files selected" });
}
And following code in my cshtml page which works fine and the controller can see the files that I upload:
<input type="file" name="files" id="files" accept="image/*;capture=camera" multiple>
<button type="button" onclick="submitform()">Submit</button>
<script>
function submitform(){
// Get files from upload
var files = $("#files").get(0).files;
// Create form data object
var fileData = new FormData();
// Loop over all files and add it to FormData object
for (var i = 0; i < files.length; i++) {
fileData.append(files[i].name, files[i]);
}
// Send files to controller
var xhr = new XMLHttpRequest();
xhr.open("POST", "/Quotes/QuoteFiles/UploadFiles", false);
xhr.send(fileData);
}
</script>
However when I try and change this to work using an Ajax call as shown below then Request.Files in the Controller always has no files. The only bit I have changed is the "Send files to controller" part:
<input type="file" name="files" id="files" accept="image/*;capture=camera" multiple>
<button type="button" onclick="submitform()">Submit</button>
<script>
function submitform(){
// Get files from upload
var files = $("#files").get(0).files;
// Create form data object
var fileData = new FormData();
// Loop over all files and add it to FormData object
for (var i = 0; i < files.length; i++) {
fileData.append(files[i].name, files[i]);
}
// Send files to controller
$.ajax({
url: '/Quotes/QuoteFiles/UploadFiles',
type: "POST",
contentType: false, // Not to set any content header
processData: false, // Not to process data
data: fileData,
success: function (result) {
alert(result);
},
error: function (err) {
alert(err.statusText);
}
});
}
</script>
I am running this in Google Chrome but I have tried IE 11 and Edge but not of them work. Can anyone tell me what I am doing wrong?
try using a fileReader instead of a formData and change the mimetype to 'text/plain; charset=x-user-defined-binary'
https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications#Example_Uploading_a_user-selected_file
I have finally found what was causing this issue, I have the following code on my _Layout.cshtml page which is there to automatically send the AntiForgeryToken on any ajax requests I make, this appears to be causing the problem because once I remove it Request.Files is not empty. I now need to see if I can find a way to add this code back in where it will not stop file uploads working:
$(document).ready(function () {
var securityToken = $('[name=__RequestVerificationToken]').val();
$(document).ajaxSend(function (event, request, opt) {
if (opt.hasContent && securityToken) { // handle all verbs with content
var tokenParam = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
opt.data = opt.data ? [opt.data, tokenParam].join("&") : tokenParam;
// ensure Content-Type header is present!
if (opt.contentType !== false || event.contentType) {
request.setRequestHeader("Content-Type", opt.contentType);
}
}
});
});
**** EDIT ****
I have now reworked this as shown below to add 'if(opt.data != "[object FormData]"' which resolves the issue by not calling the code if it is a file upload:
$(document).ready(function () {
var securityToken = $('[name=__RequestVerificationToken]').val();
$(document).ajaxSend(function (event, request, opt) {
if (opt.hasContent && securityToken) { // handle all verbs with content
// If not "FormData" (i.e. not a file upload)
if (opt.data != "[object FormData]")
{
var tokenParam = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
opt.data = opt.data ? [opt.data, tokenParam].join("&") : tokenParam;
// ensure Content-Type header is present!
if (opt.contentType !== false || event.contentType) {
request.setRequestHeader("Content-Type", opt.contentType);
}
}
}
});
});
I am working a jQuery file upload helper and I need to understand how can I append the File from the form or the Form data as a whole to the request.
I have worked with the ASP.NET code to accept image from the Request and handle the further code, but when I try to use it using jQuery $.ajax() I can't get it to work.
I have been though Stack Overflow questions, and I have tried using FormData appending the data from the input[type="file"] (input for the file element). But each time (on the server) the block that is executed that tells me there is no file with the request.
Here is the ASP.NET code (UploadFile page)
#{
var fileName = "Not running!";
if(IsPost) {
if(Request.Files.Count > 0) {
var image = WebImage.GetImageFromRequest();
fileName = Path.GetFileName(image.FileName) + " From server";
} else {
fileName = "No file attached! From Server";
}
}
Response.Write(fileName);
}
The jQuery code is as
$(document).ready(function () {
$('form input[type=submit]').click(function () {
event.preventDefault();
$.ajax({
url: '/UploadFile',
data: new FormData().append('file',
document.getElementById("image").files[0]),
type: 'POST',
success: function (data) {
$('#result').html('Image uploaded was: ' + data);
}
});
});
});
I am already scratching my head since I can't get the file content on the serverside.
How can I send the file to the server, or the entire form data to the server, anything would be welcome!
Try using handler for this and Newtonsoft.json.dll for these purpose.
For jQuery
(document).ready(function () {
$('form input[type=submit]').click(function () {
event.preventDefault();
$.ajax({
url: 'handler.ashx', // put a handler instead of direct path
data: new FormData().append('file',
document.getElementById("image").files[0]),
type: 'POST',
success: function (data) {
$('#result').html('Image uploaded was: ' + data);
}
});
});
});
In asp.net
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Web;
using Newtonsoft.Json;
public class Handler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
HttpPostedFile up = context.Request.Files[0];
System.IO.FileInfo upinfo = new System.IO.FileInfo(up.FileName);
System.Drawing.Image upimg = System.Drawing.Image.FromStream(up.InputStream);
string path = context.Server.MapPath("~/temp"); // this is the server path where you'll be saving your image
if (!System.IO.Directory.Exists(path))
System.IO.Directory.CreateDirectory(path);
string fileName;
fileName = up.FileName;
string newFilename = Guid.NewGuid().ToString();
System.IO.FileInfo fInfo = new System.IO.FileInfo(fileName);
newFilename = string.Format("{0}{1}", newFilename, fInfo.Extension);
string strFileName = newFilename;
fileName = System.IO.Path.Combine(path, newFilename);
up.SaveAs(fileName);
successmsg1 s = new successmsg1
{
status = "success",
url = "temp/" + newFilename,
width = upimg.Width,
height = upimg.Height
};
context.Response.Write(JsonConvert.SerializeObject(s));
}
I'm trying to upload a file to my J2eE spring backend. But if I set file required then it does not recognize, so therefor i conclude that it must be the way I try to send it from the front end.
HTML definition:
<form id="filesUploadForm" action="spring/uploadFile" method="post" enctype="multipart/form-data">
<input class="std" id="file" type="file" name="choose">
</form>
Javascript: (Which is triggered from another button)
function uploadFile() {
var url = 'spring/uploadFile';
var formData = $('#filesUploadForm').serialize();
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.onload = function() {
console.log('upload complete');
};
xhr.send(formData);
}
If it is relevant: here is the Java code:
#RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public void uploadFile(#RequestParam(value = "file", required = false) MultipartFile multipartFile) {
String fileName = multipartFile.getOriginalFilename();
System.out.println(fileName);
}
I think you need to change the parameter name in your Java code:
#RequestParam(value = "choose", required = false)
Valums file-uploader (now called Fine Uploader) doesn't work under Internet Explorer 9 but wors fine under Chrome.
So under IE it shows the name of the file and button CANCEL and no % of uploading.
Any clue?
UPDATES:
Solution is here as well MVC Valums Ajax Uploader - IE doesn't send the stream in request.InputStream
I know this question was filed under asp.net specifically, but it came up when I searched for "valums ajax upload IE9", so I'll post my fix here in case it helps anyone like myself regardless of language:
I was returning a JSON response from the AJAX upload request with a "application/json" content header. IE9 does not know what to do with "application/json" content (but Chrome/FF/etc do).
I fixed this by making sure to return a "text/html" MIME type http header on my json response from the server.
Now IE is no longer trying to download the response! Cheers
I am unable to reproduce the issue. Here's a full working example.
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Upload(HttpPostedFileBase qqfile)
{
var uploadPath = Server.MapPath("~/app_data");
if (qqfile != null)
{
var filename = Path.Combine(uploadPath, Path.GetFileName(qqfile.FileName));
qqfile.SaveAs(filename);
return Json(new { success = true }, "text/html");
}
else
{
var filename = Request["qqfile"];
if (!string.IsNullOrEmpty(filename))
{
filename = Path.Combine(uploadPath, Path.GetFileName(filename));
using (var output = System.IO.File.Create(filename))
{
Request.InputStream.CopyTo(output);
}
return Json(new { success = true });
}
}
return Json(new { success = false });
}
}
Index.cshtml view:
<script src="#Url.Content("~/Scripts/valums/fileuploader.js")" type="text/javascript"></script>
<div id="file-uploader">
<noscript>
<p>Please enable JavaScript to use file uploader.</p>
</noscript>
</div>
<script type="text/javascript">
var uploader = new qq.FileUploader({
element: document.getElementById('file-uploader'),
action: '#Url.Action("upload")'
});
</script>
You could also include the CSS in your Layout:
<link href="#Url.Content("~/Scripts/valums/fileuploader.css")" rel="stylesheet" type="text/css" />
It seems that is IE cache issue, if you are using Ajax & GET, add timestamp value in the get parameters for the Ajax parameters, that will do the trick like this :
$.ajax({
url : "http:'//myexampleurl.php' + '?ts=' + new Date().getTime(),
dataType: "json",
contentType: "application/json; charset=utf-8",
.
.
//more stuff
If you are using java spring
#RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "application/json")
public #ResponseBody YourObject excelUplaod(#RequestHeader("X-File-Name") String filename, InputStream is) {
// chrome or firefox
}
#RequestMapping(value = "/upload", method = RequestMethod.POST,headers="content-type=multipart/*", produces = "text/html")
public #ResponseBody ResponseEntity<YourObject> uploadByMultipart(#RequestParam(value = "qqfile") MultipartFile file) {
// IE
try {
String fileName = file.getOriginalFilename();
InputStream is = file.getInputStream();
// more stuff
} catch (Exception e) {
logger.error("error reading excel file", e);
}
}