I am trying to upload an image from the client using an AJAX call to a Rest Service. What I have is uploading the image. The size of the image matches exactly, and in windows explorer, the image preview looks like my image. But, when I double click the .png file, the image is blank.
What am I doing wrong?
Client: (event.target.files[0] is the file selected from a file dialog box)
let file = event.target.files[0];
$.ajax({
url: URL.BUILDER_URL + '/megaUpload',
type: 'POST',
contentType : "multipart/form-data",
data: file,
processData: false
});
Server:
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.APPLICATION_JSON)
#Path("megaUpload")
public Response upload(InputStream fileInputStream) throws Exception {
String uploadFileLocation = "C:\\temp\\bla.png";
OutputStream out = new FileOutputStream(new File(uploadFileLocation));
int read = 0;
byte[] bytes = new byte[1024];
out = new FileOutputStream(new File(uploadFileLocation));
while ((read = fileInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
return null;
}
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 call a Web API Controller from my UI which then gets a report from SSRS. It inserts the bytes in the content of the response and sends it to the UI where it gets downloaded as a PDF.
Inside my Web API Controller I write the report bytes to a test PDF file to inspect the contents of the pdf and to see if the data is correct, which it is. But when the PDF gets downloaded from my UI and I open it, I get a blank paged document. When I inspect the reponse content in Fiddler, I can see that the data is corrupted and doesn't match the test PDF file data.
Server side:
[HttpPost]
public HttpResponseMessage GetInstancePdf(InstancePdfModel model) {
var bytes = _digitalFormService.GetInstancePdf(model.ClientGuid, model.InstanceGuid, model.InstanceVersion);
File.WriteAllBytes(# "c:\temp\test.pdf", bytes);
var response = Request.CreateResponse();
response.Content = new ByteArrayContent(bytes);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue(DispositionTypeNames.Inline) {
FileName = "file.pdf"
};
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return response;
}
Client side:
$scope.downloadPdf = function(instance) {
$scope.isBusy = true;
digitalFormService.getInstancePdf(instance.instanceGuid, instance.instanceVersion).then(function(data) {
if (data.status === 200) {
const file = new Blob([data.data], {
type: data.headers("Content-Type")
});
if (navigator.appVersion.toString().indexOf(".NET") > 0) {
window.navigator.msSaveBlob(file, (`${instance.name} ${(new Date()).toLocaleString()}`).replace(",", ""));
} else {
//trick to download, store a file having its URL
const fileUrl = URL.createObjectURL(file);
const a = document.createElement("a");
a.href = fileUrl;
a.target = "_blank";
a.download = (`${instance.name} ${(new Date()).toLocaleString()}`).replace(",", "");
document.body.appendChild(a);
a.click();
}
} else {
debugger;
}
$scope.isBusy = false;
});
};
function getInstancePdf(instanceGuid, instanceVersion) {
var data = {
clientGuid: digitalFormConfig.clientToken,
instanceGuid: instanceGuid,
instanceVersion: instanceVersion
};
return $http({
url: digitalFormConfig.serverUrl +
"api/DigitalForm/GetInstancePdf",
dataType: "json",
data: data,
method: "POST"
}).then(function(response) {
return response;
},
function() {
return $q.reject("No Data");
});
}
I expect my downloaded PDF to be an informational document, matching the test PDF file saved inside the Web API Controller, but I get a blank document instead (same number of pages as test file, but blank).
I used Fiddler to inspect the response body. When I save the response body from within Fiddler as a pdf - everything is fine. So I am sure my server side code is correct. The problem must be somewhere on the client side.
Any help? Thanks.
I found the mistake. The bug was in the client side service. Code should look as follows:
function getInstancePdf(instanceGuid, instanceVersion) {
var data = {
clientGuid: digitalFormConfig.clientToken,
instanceGuid: instanceGuid,
instanceVersion: instanceVersion
};
return $http({
responseType: "arraybuffer",
url: digitalFormConfig.serverUrl +
"api/DigitalForm/GetInstancePdf",
dataType: "json",
data: data,
method: "POST"
}).then(function (response) {
return response;
},
function () {
return $q.reject("No Data");
});
}
The line responseType: "arraybuffer", was omitted previously.
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 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));
}
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);
}
}