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);
}
}
Related
I am developing a spring+hibernate webapp for practicing translation skill from Russian to English.
In one of my jsp pages I am retrieving all the questions from database and placing them into a table with the following columns: text in Russian, field for user's translation, button for checking the result. The goal is to save user's input into database without refreshing the page. How can I do it?
I tried several options, but none of them worked for me.
I used the solution from Send javascript variables to spring controller in my project, but nothing happened at all.
Part of "firstPage.jsp" ("/first" path in the controller):
<head>
<title>Title</title>
<script>
function searchViaAjax(id) {
var tempId = id;
alert("Start");
$.ajax({
type : "POST",
url : "./search/api/getSearchResult",
data : {id:tempId},
timeout : 100000,
success : function(id) {
alert("success");
console.log("SUCCESS: ", id);
display(id);
alert(response);
},
error : function(e) {
alert("error");
console.log("ERROR: ", e);
display(e);
},
done : function(e) {
alert("done");
console.log("DONE");
}
});
}
</script>
</head>
<body>
<button onclick="searchViaAjax(1)">Simple button</button>
</body>
Controller class:
#Controller
public class DemoController {
#RequestMapping("/first")
public String getFirst(){
return "firstPage";
}
#ResponseBody
#RequestMapping(value = "/search/api/getSearchResult", method=RequestMethod.POST)
public String getSearchResultViaAjax(#RequestParam("id") Integer id) {
System.out.println("come to ajax"+ id);
return "hello";
}
}
The "Start" message gets printed, but other messages from searchViaAjax() don't. And controller method doesn't start.
You can pass id in controller as it is no issue in your 'id', and also you can skip value attribute in #RequestParam.
#ResponseBody
#RequestMapping(value = "/search/api/getSearchResult")
public String getSearchResultViaAjax(#RequestParam("id") integer id) {
System.out.println("come to ajax"+ id);
return "hello";
}
Specify the methodType
#RequestMapping(value = "/search/api/getSearchResult", methodType=RequestMethod.POST)
It is also a good practice to use wrapper instead of primitive
#RequestParam("tempId") Integer id
the problem is in your ajax url attribute.
It should be url : "./search/api/getSearchResult",
Root Cause:
When you are about to hit your controller, it construct the url like this
http://localhost:8080/search/api/getSearchResult
and hence such resource is not available and it causes 404 not found error.
In actual the url should be
http://localhost:8080/contextroot/search/api/getSearchResult
here contextroot refers your project name.
Now if you hit url ./search/api/getSearchResult then ./ refers the base url i,e localhost:8080/contextroot and the entire url will be constructed properly.
I would like to recommend you to create global variable in JavaScript say baseUri and assign./ into it.
<script>
var baseUri="./";
</script>
In your AJAX it becomes
url : baseUri+"search/api/getSearchResult",
Hope this will help
The code from user9634982 was fine, thanks to him. The problem was because I was using slim jQuery version so my browser was giving me "$.ajax is not a function" error. And I didn't see it for hours because I didn't know where to look :facepalm: Thanks again to user9634982 for discovering browser inspector to me :D After replacing slim version to usual it still didn't work because of spring security. I added _csrf token and all worked fine.
.jsp:
<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>
<script>
function searchViaAjax(id) {
var csrfHeaderName = "X-CSRF-TOKEN";
var csrfTokenValue;
var metaTags = document.getElementsByTagName('meta');
for(var i = 0; i < metaTags.length; i++) {
var metaTagName = metaTags[i].getAttribute("name");
if(metaTagName === "_csrf_header")
csrfHeaderName = metaTags[i].getAttribute("content");
if(metaTagName === "_csrf")
csrfTokenValue = metaTags[i].getAttribute("content");
}
$.ajax({
type : "POST",
url : "./addAnsweredQuestion",
data : {id:id},
timeout : 100000,
beforeSend:function(xhr){xhr.setRequestHeader(csrfHeaderName, csrfTokenValue);},
success : function(id) {
alert("success");
console.log("SUCCESS: ", id);
display(id);
alert(response);
},
error : function(e) {
alert("error");
console.log("ERROR: ", e);
display(e);
},
done : function(e) {
alert("done");
console.log("DONE");
}
});
}
</script>
Controller:
#PostMapping(value = "/addAnsweredQuestion")
public void getSearchResultViaAjax(#RequestParam("id") Long id) {
System.out.println("come to ajax"+ id);
}
I am trying to download an excel file generated from data entered through a webpage in an MVC application.
This ajax call is executed when a button is pressed, and calls two methods in my controller. One to generate the excel file and another to download the file:
$.ajax({
type: 'POST',
data: myDataObject,
url: 'MyController/GenerateExcel/',
success: function(data) {
if (data.id != "") {
$http.get('MyController/DownloadExcel?id=' + encodeURIComponent(data.id) + '&name=' + encodeURIComponent(data.name));
return true;
}
}
});
Here is my POST method that generates the excel file and saves it to TempData:
[HttpPost]
public JsonResult GenerateExcel(Object model)
{
var fileName = "myexcel.xlsx";
var fileID = Guid.NewGuid().ToString();
var generatedReport = GenerateCustomExcel(model);
using (MemoryStream memoryStream = new MemoryStream())
{
generatedReport.SaveAs(memoryStream);
generatedReport.Dispose();
memoryStream.Position = 0;
TempData[fileID] = memoryStream.ToArray();
}
return Json(new { id = fileID, name = fileName });
}
Here is my GET method that downloads the saved excel from TempData:
[HttpGet]
public FileResult DownloadExcel(string id, string name)
{
if (TempData[id] != null)
{
byte[] fileBytes = TempData[id] as byte[];
return File(fileBytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", name);
}
else
{
return null;
}
}
This works flawlessly in Google Chrome and Firefox browsers. However, when using either Internet Explorer or Microsoft Edge browsers, the file refuses to download.
The debug console doesn't produce any useful errors. I have tried changing the returned File type to an octet stream and using window.location.href instead of a get request to download the file, but nothing appears to work. All of the functions are called and data passed between them correctly, so routes are not the problem.
Does anyone know how I can make the returned FileResult download?
Here is a solution. It uses the same code as in my question except for the changes listed here.
Add an iframe element to your webpage:
<iframe id="iFrameFileDownload" style="display: none;"></iframe>
In the javascript, instead of a call using $http.get(), set the 'src' attribute of the iframe element to the controller function url:
$.ajax({
type: 'POST',
data: myDataObject,
url: 'MyController/GenerateExcel/',
success: function(data) {
if (data.id != "") {
$("#iFrameFileDownload").attr("src", 'MyController/DownloadExcel?id=' + encodeURIComponent(data.id) + '&name=' + encodeURIComponent(data.name));
return true;
}
}
});
Another solution that I considered is using the window.open() function instead of $http.get(). (source: Download a file with mvc) However, that solution uses popups and would require users to enable popups in their browser before downloading the file.
I want to allow users to choose a file to download from a drop down list. Once they have made a selection, they can click the download button. However, the file does not download correctly.
Here is the controller for generating and returning the file:
[HttpPost]
public ActionResult DownloadReport(int? id, string templateChoice)
{
if (id == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
try
{
byte[] file = GetReport(id, templateChoice);
return File(file, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "ResumeReport.docx");
}
catch (InvalidOperationException)
{
return View();
}
}
The JavaScript function which is called upon pressing the generate report button is:
function downloadReport(InputID) {
$.ajax({
type: 'POST',
url: '#Url.Action("DownloadReport", "UserProfiles")',
data: JSON.stringify({ "ID": InputID, "TemplateChoice": $("#resumeTemplates").val() }),
contentType: 'application/json; charset=utf-8'
});
}
Opening the inspect window in chrome and going to the network tab shows the document data is received, but it does not download like a regular file.
I seemed to have found a working solution which does not reload page, does not redirect the user, and does not show any excess text in the URL upon pressing the download button. I replaced my current JavaScript function with the following:
function downloadReport(inputID) {
window.location.href = '/UserProfiles/DownloadReport/?id=' + inputID + '&template=' + $('#resumeTemplates').val();
}
And my controller now looks like:
public ActionResult DownloadReport(int? id, string template)
{
if (id == null || template == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
try
{
byte[] file = GetReport(id, template);
return File(file, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "ResumeReport.docx");
}
catch (InvalidOperationException)
{
return View();
}
}
I also added this into my RouteConfig.cs file:
routes.MapRoute(
"DownloadReport",
"{controller}/{action}/{id}/{template}",
new { controller = "UserProfiles", action = "DownloadReport", id = UrlParameter.Optional, template = UrlParameter.Optional }
);
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
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));
}