C# MVC Upload File without overwriting previous upload - c#

I have an
<input type="file" name="uploadedFile">
Model:
public HttpPostedFileBase UploadedFile { get; set; }
Uploading works fine, but in my "UploadedFile" after postback, there is always just the last upload.
I need to upload multiple files without selecting them all at once.
I know there is multiple="multiple" that you can add as attribute for the input, but there I would need to select all files at once.
Tried a List, no luck.
So what I need is:
Click Upload button. file prompt opens, select an image, click open, file prompt closes.
Repeat Step 1 choose another Image. No Postback has happened yet.
Send the form/do a post. Both Images should be available in the controller
Currently I just receive the second image.
Anyone can help me with this?
Kind Regards

never tested it but i think this should work for you
<input type="file" id="texboxID" name="uploadedFile[]">
Add File
<script>
function addFiles(){
$("#myForm").append('<input type="file" name="uploadedFile[]" />')
}
</script>
then uploading should be something like this:
function UploadFilesToServer(texboxID) {
var fileUpload = $("#" + texboxID+"").get(0);
var files = fileUpload.files;
var FilesToServer = new FormData();
for (var i = 0; i < files.length; i++) {
FilesToServer.append(files[i].name, files[i]);
}
$.ajax({
url: "url",
type: "POST",
contentType: false,
processData: false,
data: FilesToServer,
// dataType: "json",
success: function (result) {
alert(result);
},
error: function (err) {
alert(err.statusText);
}
});
}
hope i understood your question and answered you in a convenient way

you can store the selected files in FileList Array , then use this array to upload the files
html :
<input type="file" id="fileUpload">
jQuery:
$(document).ready(function(){
var fileArray=[];
$("#fileUpload").change(function(e){
var upFile = e.target.files[0];
fileArray.push(upFile);
console.log(fileArray);
});
})
I have tested the array it works fine , but I didn't test it in backend

Related

Converting string back to HTML

I took a HTML string from tinyMCE and wrapped it with jQuery html(). I am now trying to unwrap it and display it in the the view.
I get tinyMCE contents and put them into to a div. I then extract html contents of that div and pass it to my database via AJAX. I am now trying to convert the contents back into format that will allow me to display it properly.
<textarea name="tinycontent" class="form-control"
id="textFromContentEditor" value=""></textarea>
<div id="textContent" style="display:none"></div>
var sectionContent = tinyMCE.activeEditor.getContent();
sectionContent = $('#textContent').text(sectionContent).html();
$.ajax({
url: '/Home/CreateNoteContent',
async: false,
type: 'POST',
data: {
headerID: headerID,
categoryID: categoryID,
sectionContent: sectionContent
},
success: function (result) {
if (result == false) {
toastr.error("Cannot create new content")
} else {
toastr.success("Successfully created new content")
$("#feed-" + releaseID).trigger('click');
jumpTo(scrollPos);
}
}
});
My input into tinyMCE: Hello World
What gets stored in the db: <p>Hello World</p>
I want to be able to display just the text contents in the view.
I am certainly not very good at js, ajax and so on, but this is what I did in my project to display html in one of my divs from the pages -tag.
var blobs = document.getElementById('your-div-Id').innerHTML = "<h4>somethingRandom</h4>";
OBS! I believe this is javascript and therefor might not be the right solution.
Hope this helps!

How to upload files to a Web API server and send parameters along to the action?

Good day!
I am working on a ASP.NET Web API 2 project. At a certain point there is a need to upload some files. The files need to be linked to a certain FileModel (our own class). So, the client needs to send IEnumerable as parameter and the files as content. Because it's a RESTful API, both have to be sent in the same request.
The best we could come up with is the follow Controller action:
public async Task<HttpResponseMessage> Add([FromUri] IEnumerable<FileModel> fileModels)
{
// REQUEST INTEGRITY TESTING
var streamProvider = new CustomMultipartFormDataStreamProvider(fileSavePath, fileModels);
// Read the MIME multipart content using the stream provider we just created.
var work = await Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith(async t =>
{
// SOME WORK DONE AFTER SAVING THE FILES TO THE HARD DRIVE
}
}
The problem is following: the files are being uploaded with a 'multipart/form-data' Content-Type header. We need to know the contents of the FileModels before manipulating the files on the server side. If we use the MultipartFormDataStreamProvider, we can only access the non file parameters after the files have already been saved to the hard drive.
The only workaround for this we could find is to send the IEnumerable< FileModel > parameter in the URL. But given that the URL has a limited max length, this is not a reliable method.
The question is: Is there a way to submit both the IEnumerable< FileModel > fileModels parameter and the files in the body of the request and get access to the fileModels parameter before accessing the files? We also want to be able to use HttpContext.Current.Request.Files.Count;
Our current jQuery for file upload looks like this (for early testing purposes, it only supports one file upload):
$('#Upload').click(function(e) {
e.preventDefault();
var headers = new Array();
headers["SessionId"] = sessionId;
var files = $('#fileInput').get(0).files;
var formData = new FormData();
formData.append("files", files[0]);
var fileModel = $('#fileSubmission').serialize();
$.ajax({
url: "api/Submissions/Add/?" + fileModel,
headers: headers,
type: 'POST',
data: formData,
cache: false,
contentType: false,
processData: false,
dataType: 'json'
});
});
Thank you very much!
I am sorry for the late answer, but we solved the problem (I forgot that I didn't upload the answer here). Basically what we did is that we called the ReadAsMultiPartAsync method on a temporary location and then we extracted the other parameters from the request. Afterwards, we validated the input and moved the files from the temporary to the permanent location.
If you want to see the code, this is what worked for our particular example and I believe it's pretty straight-forward to adapt to any work case scenario:
On the client side, we have the following form (yes, this implementation is for demo purposes and only supports sending one file ... also, the input type="file" field is indeed outside of the form; the fileId text input is completed manually in our case, just for testing purposes)
<input type="file" name="data" id="fileInput" multiple="multiple" />
<form id="fileSubmission">
<input type="text" width="10" onchange="getFileDetails()" autocomplete="off" placeholder="FileId" name="files[0].Id" id="fileId" />
<input type="hidden" name="files[0].FileName" id="FileName"/>
<input type="hidden" name="files[0].Extension" id="Extension"/>
<input type="hidden" name="files[0].EntityId" id="EntityId"/>
<br /><br />
<input type="submit" id="Upload" value="Upload" />
</form>
where getFileDetails() populates the other input fields. Also, the form is being sent to the server by using the following jQuery/Javascript:
$('#Upload').click(function(e) {
e.preventDefault();
var courseId = $('#courseId').val();
var fileId = $('#fileId').val();
if (!courseId || !fileId) {
return;
}
var headers = new Array();
headers["SessionId"] = sessionId;
headers["contentType"] = "application/json; charset=UTF-8";
var formData = new FormData();
var opmlFile = $('#fileInput').get(0).files;
// this is like the model we're expecting on the server
var files = [];
files.push({ 'Id': $('#fileId').val(), 'OriginalFileName': opmlFile[0].name, 'FileName': $('#FileName').val(), 'Extension': $('#Extension').val(), 'EntityId': $('#EntityId').val() });
formData.append("fileModels", JSON.stringify(files));
formData.append("File_0", opmlFile[0]);
$.ajax({
url: "api/Courses/" + courseId + "/Submissions/Add/",
headers: headers,
type: 'POST',
data: formData,
cache: false,
contentType: false,
processData: false,
dataType: 'json'
});
});
On the server side, we have the following :
// POST: api/Courses/{courseId}/Submissions/Add
[HttpPost]
[ValidateModelState]
[ValidateMimeMultipartContent]
[PermissionsAuthorize(CoursePermissions.CanCreateSubmissions)]
public async Task<HttpResponseMessage> Add(int courseId)
{
// the same as in the jQuery part
const string paramName = "fileModels";
// Put the files in a temporary location
// this way we call ReadAsMultiPartAsync and we get access to the other data submitted
var tempPath = HttpContext.Current.Server.MapPath("~/App_Data/Temp/" + Guid.NewGuid());
Directory.CreateDirectory(tempPath);
var streamProvider = new MultipartFormDataStreamProvider(tempPath);
var readResult = await Request.Content.ReadAsMultipartAsync(streamProvider);
if (readResult.FormData[paramName] == null)
{
// We don't have the FileModels ... delete the TempFiles and return BadRequest
Directory.Delete(tempPath, true);
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
// The files have been successfully saved in a TempLocation and the FileModels are not null
// Validate that everything else is fine with this command
var fileModels = JsonConvert.DeserializeObject<IEnumerable<FileModelExtension>>(readResult.FormData[paramName]).ToList();
// AT THIS POINT, ON THE SERVER, WE HAVE ALL THE FILE MODELS
// AND ALL THE FILES ARE SAVED IN A TEMPORARY LOCATION
// NEXT STEPS ARE VALIDATION OF THE INPUT AND THEN
// MOVING THE FILE FROM THE TEMP TO THE PERMANENT LOCATION
// YOU CAN ACCESS THE INFO ABOUT THE FILES LIKE THIS:
foreach (var tempFile in readResult.FileData)
{
var originalFileName = tempFile.Headers.ContentDisposition.FileName.Replace("\"", string.Empty);
var localTempPath = tempFile.LocalFileName;
}
}
I hope this will help anyone out there trying to submit files and other parameters at once to the server by using Post requests! :)
NOTE: Some of the attributes used on the server are custom. PermissionAuthorize, ValidateModelState and ValidateMimeMultiPartContent are custom Filters we have used. The implementation of the latter two has been inspired by http://benfoster.io/blog/automatic-modelstate-validation-in-aspnet-mvc
The multipartcontent attribute just does a check on actionContext.Request.Content.IsMimeMultipartContent(), like this:
public class ValidateMimeMultipartContent : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (!actionContext.Request.Content.IsMimeMultipartContent())
{
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.UnsupportedMediaType, Messages.UnsupportedMediaType);
}
}
}

Passing an image from JavaScript to C# in an ASP.NET app?

I have an Image variable loaded in a JavaScript app, and I want to pass it to a C# method in my ASP.NET app (so I can store it in a database). The only problem I am having is getting the image's data itself to the C# method. I tried using an AJAX call (it's a GET) with the C#'s method's byte[] parameter set to the Image's .Picture, but the byte[] is empty.
How do I get the image's data from the JavaScript script to the C# method?
UPDATE:
I tried copying the image to a canvas using drawImage on the canvas's rendering context, but the image has to come from my local computer, so when I subsequently try to call canvas.toDataURL, it throws a DOM Security error.
I also considered using FileReader to get the data directly rather than loading it as an image, but, for political reasons, I have to support browsers that don't implement FileReader yet.
Am I asking for something that just isn't possible in JavaScript? (There must be a way of doing this (not necessarily in JS), as Facebook implements loading images from the client computer's local file system.)
I don't know how you load your image in javascript app. But when i faced the same issue , i did it in the follwing way.
HTML
<input id="imgInput" type="file" name="file" />
<img id="imagePreview" src="" alt="Item Image" width="96" height="80"/>
<input id="Button1" type="button" value="save image" onclick="saveimage();"/>
JS
$(document).ready(function () {
$("#imgInput").change(function () {
readURL(this);
});
});
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#imagePreview').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
function saveimage() {
var images = $('#imagePreview').attr('src');
var ImageSave = images.replace("data:image/jpeg;base64,", "");
var submitval = JSON.stringify({ data: ImageSave });
$.ajax({
type: "POST",
contentType: "application/json;charset=utf-8",
datatype: "json",
data: submitval,
url: "your url",
success: function (data) {
//code for success
}
});
}
.CS
[WebMethod]
public static string saveimage(string data) {
byte[] imgarr = Convert.FromBase64String(data);
/* Add further code here*/
}

ASP.NET MVC post controller get json, generate file and return it

I have an ajax post request:
function downloadElevationMap() {
var jsonData = ko.toJSON(mod.SelectedItem);
$.ajax({
url: '/Home/GetData/',
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: jsonData,
success: function (data) {
console.log("OK");
},
});
}
The controller method recive data correct. The code is presented below:
public FileStreamResult GetData(Mv jsonData)
{
var resultAll = jsonData.Data.Select(d => d.y).ToList();
var str = new StringBuilder();
_fileName = "ses"+jsonData.Path;
foreach (var d in resultAll)
{
str.Append(d + " ");
}
var byteArray = Encoding.ASCII.GetBytes(str.ToString());
var stream = new MemoryStream(byteArray);
return File(stream, "text/plain", string.Format("{0}.txt", _fileName));
}
Mv - is my class that represent data. When debug the both str and stream variable contain correct data.
Function downloadElevationMap() is called by onclick="downloadElevationMap()"
I just want when downloadElevationMap() is called the GetData controller return a file for download. But simply nothing happend. Where the error is?
well you dont need ajax to do that try this
window.location="download.action?para1=value1...."
for your needs you can do some thing like this
window.location="/Home/GetData/?"+$.param(jsonData )
I'm fairly sure what you are doing is swallowing the data in the success callback in the AJAX call - all your code will do is download the file, call the success callback, and then just print "OK" to the console.
As Anto said, you don't need AJAX (and, indeed, should not be using AJAX) for this. His answer is absolutely correct, provided you can use a GET string. If you need to use a POST request, create a form with hidden inputs and submit that - something like:
HTML
<form action="/Home/GetData" method="POST" id="dataToSubmit">
<input type="hidden" name="param1" value="value1" />
<input type="hidden" name="param2" value="value2" />
<input type="hidden" name="param3.param4" value="value3" />
</form>
JS
function downloadElevationMap() {
// Write code to map your jsonData to your form elements
$('#dataToSubmit').submit();
}
You could make the form dynamically if you wish. You might be able to update your page to post directly with a submit button.
One final note, you don't need to submit the data as Json. If you have
{
"param1": "value1",
"param2": "value2",
"param3": {
"param4": "value3"
}
}
then if you just use the format in the form above, it will submit fine - this reference explains how to submit to deep models.

How can I get a posted file on server-side from an Ajax Request in asp.net-webpages?

Using the helpful information I found here:
How can I upload files asynchronously?
I was able to get form data to the server-side with the following jQuery (very slightly modified from the link above):
$('#addFileInput').change(function () {
var file = this.files[0];
name = file.name;
size = file.size;
type = file.type;
//Your validation
});
$('.submitFile').click(function () {
var formData = new FormData($("#fileUploadForm"));
$.ajax({
url: '/AJAX Pages/Compute_File_Upload.cshtml', //Server script to process data
type: 'POST',
xhr: function () { // Custom XMLHttpRequest
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) { // Check if upload property exists
myXhr.upload.addEventListener('progress', progressHandlingFunction, false); // For handling the progress of the upload
}
return myXhr;
},
//Ajax events
beforeSend: function () {
$("#progressBar").css("visibility", "visible");
},
success: function (response) {
$(".editLabelTitle").text(response);
},
//error: errorHandler,
// Form data
data: formData,
//Options to tell jQuery not to process data or worry about content-type.
cache: false,
contentType: false,
processData: false
});
});
function progressHandlingFunction(e) {
if (e.lengthComputable) {
$('progress').attr({ value: e.loaded, max: e.total });
}
}
Here's the HTML that is involved:
<div class=\"addFileBox\">
<div class=\"editPageSubTitle dragHandle\">
Add File
<button id=\"closeAddFileBox\">X</button>
</div>
<div class=\"innerAddFileDiv\">
<form id=\"fileUploadForm\" enctype=\"multipart/form-data\">
<input id=\"addFileInput\" name=\"addFileInput\" type=\"file\" />
</form>
<br/>
<progress id=\"progressBar\"></progress>
<br/>
<button class=\"submitFile\">Submit File</button>
</div>
</div>
The Ajax request in and of itself works fine. The problem comes when I don't know how to get the file on the server-side code (normally I would just find the input with the Request.Files["someFileId"]) but as all formData is sent, this isn't working the way I am familiar with.
C# CODEBEHIND
#{
Layout = "";
if(IsAjax)
{
var file = Request.Files["addFileInput"];
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/CMS Files/UtilityBilling"), fileName);
file.SaveAs(path);
}
}
What is the proper way to access the given file, considering my scenario and environment?
Try this from codebehind:
HttpFileCollection filesCollection = HttpContext.Current.Request.Files;
var fileName = filesCollection[0];
string filePath = Path.Combine(HttpContext.Current.Server.MapPath("~/SaveDir"), fileName.FileName);
fileName.SaveAs(filePath);

Categories

Resources