Kendo UI multiple files upload issue - javascript

I am using a Kendo File Upload control to upload multiple files. Only few of the files are getting uploaded (especially first and last) or some random ones. Is there any solution for this ?
Index.cshtml :
<input name="files" id="files" type="file" multiple="multiple" />
JS File :
$("#files").kendoUpload
({
async: {
saveUrl: "/Controller/GetUserUploadedFiles",
removeUrl: "/Controller/Remove",
autoUpload: false,
allowmultiple: true
},
select: function (e) {
onSelect(e);
},
success: function (e) {
},
error: function (e) {
}
});
//Controller Method
[HttpPost]
public void GetUserUploadedFiles(IEnumerable<HttpPostedFileBase> files)
{
//Custom logic here
}
Also, it would be great if i can get all the files as Enumerable in one controller method call rather than having it called multiple times for multiple files.
Is there anything i am missing or doing wrong ?
Thanks,
Srini

This code will upload all the files that were selected in Kendo Upload, and then run code on each.
[HttpPost]
public void GetUserUploadedFiles()
{
Request.Content.LoadIntoBufferAsync().Wait();
var result = Task.Factory
.StartNew(() => Request.Content.ReadAsMultipartAsync().Result,
CancellationToken.None,
TaskCreationOptions.LongRunning,
TaskScheduler.Default).Result;
var contents = result.Contents;
HttpContent httpContent = contents.First();
Stream file = httpContent.ReadAsStreamAsync().Result;
if (file.CanRead)
{
// Code that will be executed on each file
}
}
You can get the filename by using:
string filename = httpContent.Headers.ContentDisposition.FileName.Replace("\"", string.Empty);
You can get the uploaded file media type by using:
string uploadedFileMediaType = httpContent.Headers.ContentType.MediaType;

IIRC, the kendo batch option will only upload the files as a collection if selected at the same time (browse, then select more than one file). Once you select additional file(s) they will be sent in another request. The only way you can force the files to be posted during the same request is to use the synchronous mode rather than async. Good luck.

Related

Upload file having special character in name using Angular ngf-select

I am working on Angular2 application with spring boot in back-end. In application there is feature to upload file on server. The code to upload file working fine.
I am using ngf-select to choose file. It works well when file name is without special characters.
<input type="file" name="file" ng-model="obj.fileModel" ngf-select accept="file_extension">
The problem occurs when I choose file having special character like my name neelam shrma ## !! %%% ggg %.json
Upload js code is :
var formData = new FormData();
formData.append("fileObj", obj.fileModel);
UploadFile.save(formData, onUploadSuccess, onUploadError);
As file obj.fileModel having File object with special character name, so it do not call resource method to upload file
Also I have tried by updating the file name withe encoding, but as file object is read-only, so won't allowing me to change the name, also created new file object with encoded file name, but didn't worked.
Resource Method :
public boolean uploadMyFile(MultipartFile mpfile) throws IOException {
...
....
File file = new File(myFolder + File.separator + file.getOriginalFilename());
mpfile.transferTo(file);
......
......
}
So the file having special character not calling my resource method : uploadMyFile(..) and throwing 500 server error.
How to resolve the issue of uploading file having special character using angularJs ngf-select?
Add a filter as below
.filter('decodeURL', function () {
return function (text) {
if (text) {
return window.encodeURIComponent(text);
}
}
});
and below html
<img src="{{itemDetails.LargeImageName | decodeURL}}" />

How to use file Uploader in kendoui with angularjs?

I'm using kenoui uploader in angularjs,
i can able to upload files but i can't able to save that file.
my questing was how to i given saveUrl and removeUrl in option
this is my code below,
index.html
<input name="files"
type="file"
kendo-upload
k-options="fileAttachmentConfig"
k-select="onSelect" />
index-ctrl.js
$scope.fileAttachmentConfig = {
async: {
saveUrl: 'app/images/client',
removeUrl: 'remove',
autoUpload: false
}
}
So How to handle that saveUrl and removeUrl also how to save file to my local path?
saveUrl and removeUrl are path to your Save/Remove method in Controller or something like that.
You must implement method in backend (server side) where you can save file on server (your local path).
Check demos in this examples or C# demo server side.

Blueimp multiple chunk upload with form data

I want to chunk upload multiple files with form data. Save form data to database and image to a perticualr folder.
I'm using blueimp upload here is my Fiddle.
The JavaScript codde i'm using
$(function () {
$('#fileupload').fileupload({
maxChunkSize: 5000,
previewMaxHeight: 210,
previewMaxWidth: 210,
url: '/echo/json'
});
$('#fileupload').bind('fileuploadsubmit', function (e, data) {
var inputs = data.context.find(':input');
if (inputs.filter('[required][value=""]').first().focus().length) {
return false;
}
data.formData = inputs.serializeArray();
});
});
Chunk upload is working fine, but if I save data to database multiple entries are created.
The number of entries created in database is equal to number chunk uploaded.
The PHP code that i'm using is ( taking help of blueimp PHP class https://github.com/blueimp/jQuery-File-Upload/blob/master/server/php/UploadHandler.php )
public function postUpload()
{
$upload_handler = new UploadHandler(); // Blueimp class
$this->file->create(Input::all()); // This code is executed multiple times
}
So main trouble is $this->file->create(Input::all()); code is execute multiple times as the number of chunks uploaded, where as I want it to be executed once when file is uploaded successfully.
Also want to name file of the file that is uploaded to save it to database.
You need to first upload all the chunks and on the last chunk execute your own logic. So here is how you can do this.
You should first extract the range info from http header Content-Range. You can look at this answer for how to. Then you should check if that's the last chunk.
And if it is the last chunk you simly execute your business logic there.
Even if it is a late answer, it might help someone.

Opening a JSON file from javascript

I have a C# functoin in my MVC application that returns a JSON representation of a csv file. I am trying to catch that in javascript and open the file. Basically I want the browser do its thing and let the user decide if he want to open it, save it or cancel. I am unable to get that popup to ask me to open the file. Below are the functions
C# Function
[HttpPost]
public ActionResult ExportToCsv(string fileContents, string fileName)
{
fileContents = fileContents.Replace("-CARRIAGE-", "\r\n");
return Json(new { url = File(Encoding.UTF8.GetBytes(fileContents), "text/csv", fileName) }); ;
}
This is the javascript where I am making the ajax call to the function
$("#btnExport").click(function (event) {
event.preventDefault();
var csv = table2csv(noteTypeTable, "full", "Table.dataTable", "noteTypes");
$.ajax({
url: "/Admin/Admin/ExportToCsv/?fileContents=" + csv + "&fileName=NoteTypes.csv",
type: 'Post',
success: function (result) {
window.open(result.url);
}
});
});
I know I am missing something. Can someone please help.
EDIT
After reading through all the potential answers and comments, this is what I am trying to achieve. So if my code is all horribly wrong please let me know.
I have a grid and I have an export to excel button. I have a method that converts the data i want into comma delimited text in javascript itself. I need to present this to the user as a downloadable csv file. For this I was creating the File object using the controller method. The previous incarnation was a Get method and I faced limitations due to querystring length restrictions. So I tried converting it to a POST method and it is not working.
This is the previous version of the code that works for smaller amounts of data
Javascript
$("#btnExport").click(function (event) {
event.preventDefault();
var csv = table2csv(noteTypeTable, "full", "Table.dataTable", "noteTypes");
window.location.href = "/Admin/Admin/ExportToCsv/?fileContents=" + csv + "&fileName=NoteTypes.csv";
});
C# Function
[HttpGet]
public ActionResult ExportToCsv(string fileContents, string fileName)
{
fileContents = fileContents.Replace("-CARRIAGE-", "\r\n");
return File(Encoding.UTF8.GetBytes(fileContents), "text/csv", fileName);
}
Hope this now gives you all more context. Basically I needed to convert my GET method to a POST method and use it from Javascript.
If you use ajax, you're expected to handle the result in code. But you can't trigger a file download (directly) that way.
Instead, create a (hidden) form and post it to a (hidden) iframe (by giving the iframe a name and specifying that as the target of the form), making sure that the response specifies the header Content-Disposition: attachment. That will trigger the browser to offer to save the file. Optionally in the header you can suggest a filename for the file by adding ; filename="fname.ext" to the header value. E.g. Content-Disposition: attachment; filename="fname.ext".
The client-side looks something like this:
$("#btnExport").click(function (event) {
event.preventDefault();
var csv = table2csv(noteTypeTable, "full", "Table.dataTable", "noteTypes");
var frame = $('iframe[name="formreceiver"]');
if (!frame.length) {
frame = $('<iframe name="formreceiver"></iframe>').appendTo(document.body).css("display", "none");
}
var form = $("#senderform");
if (!form.length) {
form = $('<form id="senderform"></form>').appendTo(document.body);
}
form = form[0]; // Raw DOM element rather than jQuery wrapper
form.target = "formreceiver";
form.action = "/Admin/Admin/ExportToCsv/?fileContents=" + csv + "&fileName=NoteTypes.csv";
form.method = "POST";
form.submit();
});
The server side is just a standard form response with the Content-Disposition header.
I've used this technique for years, with browsers from IE6 onward. My usual setup already has the iframe in the markup (rather than creating it as above), but other than that this is basically what I do.
Note that it's important you're doing this in response to a button click by the user. If you weren't, there would be popup-blocker issues.
You can't save binary files using ajax - it's restricted due to security reasons. If you'd like the user to save the file - return a binary stream from your controller as you post the data back in JSON format (ie if the user wants to save it).
I've done a similar thing here: How to properly create and download a dynamically generated binary *.xlsx file on .net MVC4?
Maybe save it as a json file instead and load in the current page's DOM. Although I though I am confused, don't you just have a JSON response containing a URL to your CSV file is which is just that a CSV file, not a JSON representation of CSV?
$("#btnExport").click(function (event) {
event.preventDefault();
var csv = table2csv(noteTypeTable, "full", "Table.dataTable", "noteTypes");
$.ajax({
url: "/Admin/Admin/ExportToCsv/?fileContents=" + csv + "&fileName=NoteTypes.json",
type: 'Post',
success: function (result) {
var myDummyElement = $('<div>'); //dummy div so you can call load
myDummyElement .load('result.url #myJson');
}
});
});
<div id="myJson"></div>
[HttpPost]
public ActionResult ExportToCsv(string fileContents, string fileName)
{
//change fileName to be a .json extension
fileContents = fileContents.Replace("-CARRIAGE-", "\r\n");
return Json(new { url = File(Encoding.UTF8.GetBytes(fileContents), "text/csv", fileName) }); ;
}

Forcing Backbone to save an attribute as a file

Is there a way to use Model.set and Model.save in a way that will force Backbone to send the data to the server as a file (as if you were submitting a form with an <input type="file"> tag?
The short answer is no. The long answer is, sort of.
This doesn't really have anything to do with Backbone and instead is about being able to AJAX a file in the browser. The solution is to use the File API from HTML 5. Below is an example of how you would do that with a Backbone model.
Let's assume we have a User model and we want to save an avatar file on that model.
// Backbone Model JS
User = Backbone.Model.extend({
readAvatar : function (file, callback) {
var reader = new FileReader(); // File API object for reading a file locally
reader.onload = (function (theFile, self) {
return function (e) {
// Set the file data correctly on the Backbone model
self.set({avatar_file_name : theFile.name, avatar_data : fileEvent.target.result});
// Handle anything else you want to do after parsing the file and setting up the model.
callback();
};
})(file, this);
reader.readAsDataURL(file); // Reads file into memory Base64 encoded
}
});
// Somewhere in your view JS
this.$("input[type='file']").change(function (event) {
var file = e.originalEvent.target.files[0];
userModel.readAvatar(file, userModel.save);
});
// HTML
<form><input type="file" name="avatar"/></form>
Now on your back end you need to handle the file coming through as Base64 encoded data.
A couple of warnings:
If you need extensive browser support then this solution probably won't work for you.
Base64 encoding a file is going to increase the amount of data sent over the wire by about 30%.

Categories

Resources