I want upload large file(600 MB) in ASP.Net Mvc with Kendo Uploader But I get flowing Exception:
OutOfMemoryException
Web.config: maxRequestLength and maxAllowedContentLength were set
before too
maxRequestLength = "2097152" maxAllowedContentLength = "2147483647"
Saeid is my coworker (really sharp man) and we solve the solution after a lot research,
so we think share it with you....
first of all
i want to describe solution.
we want to upload large file asynchronous with kendo ui upload widget but we have a problem.
when we upload large file (600MB or larger), application throw out of memory exception because application load 600MB to ram and .....
solution
1- if you want to use kendo ui uploader you must use following html code
<form method="post" enctype="multipart/form-data" action="api/UploadFile">
<input name="files" id="files" type="file" />
</form>
$("#files").kendoUpload({
async: {
saveUrl: "/api/UploadFile",
autoUpload: true
},
success: onSuccess,
upload: onUpload
});
1-1:you must use enctype="multipart/form-data" for async upload,
1-2:action="api/UploadFile" i want to upload file to UploadFile web Api
if you want use html input file,please you below html code
<form method="post" enctype="multipart/form-data" action="api/UploadFile">
<input name="files" id="files" type="file" />
</form>
2-Api must be has below code
public class UploadController : ApiController
{
public Task<HttpResponseMessage> PostFormData()
{
// Check if the request contains multipart/form-data.
if (Request.Content.IsMimeMultipartContent() == false)
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
var task = Request.Content.ReadAsMultipartAsync(provider).
ContinueWith<HttpResponseMessage>(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
}
foreach (MultipartFileData file in provider.FileData)
{
string directory = Path.GetDirectoryName(file.LocalFileName);
string filename = file.Headers.ContentDisposition.FileName.Replace(#"\","").Replace(#"""","");
File.Move(file.LocalFileName, Path.Combine(directory, filename));
}
return Request.CreateResponse(HttpStatusCode.OK);
});
return task;
}
}
2-1 : we determind app_data folder to save uploaded file
Now you can upload file Async but if you choose large file then you get out of memory exception
for resolve this problem ,you should say to mvc to not buffer data in UploadFile Api.
it has easy solution
Please Read following Article for solve it.
Dealing with large file
Related
I am trying to use DropzoneJS to upload multiple photos to a webapplication.
The Upload view contains following
<div class="jumbotron">
<form action="/Upload"
class="dropzone"
id="dropzoneJsForm"
style="background-color:#00BFFF"></form>
</div>
And the Upload controller contains this
[HttpPost]
public async Task<IActionResult> Upload(IFormFile file, IHostingEnvironment _environment)
{
var uploads = Path.Combine(_environment.WebRootPath, "uploads");
if (file.Length > 0)
{
using (var fileStream = new FileStream(Path.Combine(uploads, file.FileName), FileMode.Create))
{
await file.CopyToAsync(fileStream);
}
}
return RedirectToAction("Index");
}
When I run the application in debug mode and add files I see the progressbar and the checkmark indicating success. But no files has been uploaded in the upload folder in wwwroot.
I have app.UseStaticFiles() in the Configure method.
Target framework: .Net Core 2.0
I am using Visual Studio 2017 Professional latest version
<webconfig>
<system.web>
<httpRuntime maxRequestLength="15360" requestLengthDiskThreshold="15360"/>
</system.web>
'consider using fileupload='multiple' attribute on control
I found the mistake. A stupid beginner mistake. When I changed the name of the controller method to Index it worked.
Greeting.
I want to upload an image together with a description to the server by using ajax.
The fileupload works fine, although I can't figure out how to also extract the text entered.
Basically the form looks like this:
<form id="uploader">
<input id="fileInput" type="file" multiple>
<input type="text" id="fileText" name="fileText" value=" " />
<input type="submit" value="Upload file" />
</form>
The script for the upload to the server looks like this:
document.getElementById('uploader').onsubmit = function () {
var formdata = new FormData(); //FormData object
var fileInput = document.getElementById('fileInput');
//Iterating through each files selected in fileInput
for (i = 0; i < fileInput.files.length; i++) {
//Appending each file to FormData object
formdata.append(fileInput.files[i].name, fileInput.files[i]);
}
//Creating an XMLHttpRequest and sending
var xhr = new XMLHttpRequest();
xhr.open('POST', '/Controller/Action');
xhr.send(formdata);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
}
return false;
}
And on the serverside, in the controller for the related action:
public JsonResult Upload(){
for (int i = 0; i < 9; i++){
HttpPostedFileBase file = Request.Files[i]; //Uploaded files
//Do stuff with uploaded files
}
}
What I've tried:
Changed the Upload method to take in a string parameter named fileText.
Changed the script to also appent the text to the formdata with these two lines inside the for-loop:
var fileText = document.getElementById('fileText');
formdata.append(fileText.value, fileText.value)
I'm probably missing something in both of my trials but I can't seem to figure out what. Please help!
Regards,
Chris
Changed the Upload method to take in a string parameter named fileText.
Correct.
Changed the script to also appent the text to the formdata with these two lines inside the for-loop:
Incorrect. You shouldn't be doing this inside the loop because you have only one input field for the text, so you can send only 1 value. So move this code outside of the loop. Also you should specify the correct name when appending to the FormData which must match your controller action parameter name:
var fileText = document.getElementById('fileText');
formdata.append('fileText', fileText.value);
My project is an online mock toefl test. In speaking section I want to upload a recorded file (audio) to server. for recording im not using flash and its only js.
I searched and find something useful but the server is php. and i cant turn the codes to asp.net (web form). please help me out.
In php i used this code in js :
function uploadAudio(mp3Data){
var reader = new FileReader();
reader.onload = function(event){
var fd = new FormData();
var mp3Name = encodeURIComponent('audio_recording_' + new Date().getTime() + '.mp3');
console.log("mp3name = " + mp3Name);
fd.append('fname', mp3Name);
fd.append('data', event.target.result);
$.ajax({
type: 'POST',
url: 'upload.php',
data: fd,
processData: false,
contentType: false
}).done(function(data) {
//console.log(data);
log.innerHTML += "\n" + data;
});
};
reader.readAsDataURL(mp3Data);
}
and this code in upload.php:
<?php
if(!is_dir("recordings")){
$res = mkdir("recordings",0777);
}
// pull the raw binary data from the POST array
$data = substr($_POST['data'], strpos($_POST['data'], ",") + 1);
// decode it
$decodedData = base64_decode($data);
// print out the raw data,
//echo ($decodedData);
$filename = urldecode($_POST['fname']);
// write the data out to the file
$fp = fopen('recordings/'.$filename, 'wb');
fwrite($fp, $decodedData);
fclose($fp);
?>
How can i do this in asp.net, tanks.
You can use jQuery File Uploader on an aspx page. Your client can simply communicate withe an ashx handler at the server side.
https://evolpin.wordpress.com/2011/09/11/asp-net-ajax-file-upload-using-jquery-file-upload-plugin/
One method, and perhaps the most simple solution, is to just use the <asp:FileUpload> control, and hide it from view. Then again, although this works well if you want the user to choose the files they're uploading, it might not be the best solution if you want to implement some kind of HTML5 drag'n'drop solution, etc.
Coincidentally, I spent pretty much all of last week studying how to upload files via javascript to ASP.NET web forms. I developed a drag and drop interface that uses HTML5, and also developed a fail-over method with which the user could choose and upload their files via the <asp:FileUpload> control.
Due to the feature being low-priority, we only fully developed the <asp:FileUpload> control, but I'm happy to share that feature with you here:
HTML
We're going to create an ASP file upload control, and hide certain parts of it. The rest of it, we can add styles to (or do whatever in javascript and CSS) to make it look fancy and customized. The CONTINUE BUTTON
<!-- Allow user to upload the file via the fallbackuploader -->
<div id="fallbackUploader" class="uploader-item-fallbackuploader uploader-item fallbackuploader step-container">
<div class="fallbackuploader-item-uploadcontrols fallbackuploader-item uploadcontrols">
<!-- Uploader Label (note: this serves as the visible "choose files" button too) -->
<label id="uploader_choose_files_button" class="uploadcontrols-item uploadcontrols-item-label button animated" for="mainContent_subContent_fbu_fileuploader">
Choose Files
</label>
<!-- Choose Files button (**NOTE: you'll want to make this control invisible. Try not to set the display to none, as that may cause ASP to omit rendering it -->
<asp:FileUpload ID="fbu_fileuploader" CssClass="uploadcontrols-item-aspfileloader uploadcontrols-item aspfileloader" runat="server" />
<!-- Continue button (NOTE: this button triggers the event that on the server side that will actually handle the file upload -->
<asp:Button ID="fbu_fileuploaderButton" runat="server" Text="Continue" ClientIDMode="Static"
CssClass="uploadcontrols-item-button-upload uploadcontrols-item-button uploadcontrols-item button-upload button continue-button hidden disabled animated" />
<!-- Cancel button -->
<div id="chooseFilesCancelButton" class="uploadcontrols-item-uploadcontrols-item-button
uploadcontrols-item cancel-button hidden disabled button animated">
Go Back
</div>
</div>
</div>
Javascript
// Organizational container for the file uploader controls.
var aspUploadControlsContainer = $('.fallbackuploader-item-uploadcontrols');
// ASP control that chooses and loads the file.
var aspFileLoader_ele = aspUploadControlsContainer.children('.uploadcontrols-item-aspfileloader'),
// element that represents the "choose files" button.
aspUploaderChooseFilesLabel = aspUploadControlsContainer.find('.uploadcontrols-item-label'),
// ASP button that loads the file
aspFileLoaderButton_ele = aspUploadControlsContainer.children('.uploadcontrols-item-button'),
// the element created by the actual ASP "<asp:FileUpload>" control tag.
aspFileUploadControl_ele = aspUploadControlsContainer.find('input.uploadcontrols-item-aspfileloader'),
// the message/alert container
messagebox_ele = $('.uploader-item-messagebox');
// ------------------------------------------------------------
// Bind the 'click' and 'change' events to the file uploader
// ------------------------------------------------------------
function bindAspUploadControlEvents() {
aspFileLoader_ele.on('change', function () { // add the on-change event for the file uploader.
console.log('File changed ...');
if (!aspUploaderChooseFilesLabel.hasClass('upload-disabled')) {
console.log('Choose-files label not disabled ...');
fileSelected(); // perform the file-selected actions.
}
});
};
// ------------------------------------------------------------
// Validate the selected file name and adjust the uploader.
// ------------------------------------------------------------
function fileSelected() {
console.log('File selected...');
var f = aspFileLoader_ele.val() || '';
f = f.replace('C:\\fakepath\\', '') || ''; // get the file name <-- ASP.NET masks the path as C:\\fakepath\\ for security purposes...we'll just take that part out.
var xlRegex = /.(xlsx|xls)$/i; // set the regex to test for accepted file extensions.
if (f.length && !(f.match(xlRegex))) {
// --------------------------- FAILED - show a message -----------------------------------------------------------------
console.log('File-name invalid. Displaying error message ...');
convertCFlabelToButton(); // <-- converting the label to a button and visa versa is probably a round-about way of doing what we wanted, but we were doing some other stuff with it that kind of made it a necessary evil :)
deactivateChooseFilesCancelButton(); // if nothing selected, disable and hide cancel button <-- these functions just do some fluffy stuff that you probably won't need.
deactivateUploaderContinueButton(function () { // if nothing selected, disable and hide continue button <-- these functions just do some fluffy stuff that you probably won't need.
messagebox_ele.text("You've selected a file with an invalid file name. Please make sure the file extension ends with \".xlsx\".").show(); // show the error message.
});
} else if (f.length && f.match(xlRegex)) {
// --------------------------- PASSED -----------------------------------------------------------------
console.log('File-name validated. Hiding messages...');
messagebox_ele.text('').hide(); // reset and hide any messages
console.log('Messages hidden.');
convertCFbuttonToLabel(f, function () { // this converts the button to a label with the given file name as its text
activateUploaderContinueButton(function () { // show and enable the choose-files continue-button
activateChooseFilesCancelButton() // show and enable the choose-files cancel-button
});
});
} else {
// --------------------------- FAILED - hide message -----------------------------------------------------------------
console.log('No file detected. Returning to default state ...');
messagebox_ele.text('').hide(); // hide any messages
// reset the label to defaults
convertCFlabelToButton();
// ------------------------------------------------------------------------------------------------------------------------------
};
}
CODE-BEHIND
Now we just need to add the VB.NET (or C#) to handle the click-event for the continue button.
Protected Sub fbu_fileuploaderButton_Click(sender As Object, e As EventArgs) Handles fbu_fileuploaderButton.Click
If fbu_fileuploader.HasFile Then
Dim FileName As String = Path.GetFileName(Path.GetRandomFileName())
Dim Extension As String = Path.GetExtension(fbu_fileuploader.PostedFile.FileName)
Dim FolderPath As String = ResolveUrl("~/" & ConfigurationManager.AppSettings("FolderPath"))
Dim FilePath As String = Server.MapPath(FolderPath + FileName)
fbu_fileuploader.SaveAs(FilePath)
GetExcelSheets(FilePath, fbu_fileuploader.PostedFile.FileName, FileName, Extension, "Yes")
End If
End Sub
Other Caveats
We did a couple things in the above code that I did not explain, such as the "FolderPath" application setting (we used this in CODE-BEHIND section to determine where the file should be saved). If you've never used application settings in the web.config, it's very simple. For the sake of the above example, we would add the following snippet between our <configuration> tags:
<appSettings>
<add key="FolderPath" value="uploads/"/>
</appSettings>
I can then access the value of this appSetting using
ResolveUrl("~/" & ConfigurationManager.AppSettings("FolderPath"))
or
ResolveUrl(String.Format("~/{0}", ConfigurationManager.AppSettings("FolderPath")))
Also, I stopped with the function to "getExcelSheets" because that's more specific to my application, and probably beyond the scope of this tutorial.
Additional Resources
I have a good habit of methodically saving useful bookmarks. Here is what I have from my "File Uploader" section...
CodeProject.com - File Upload with ASP.NET
Reading files in Javascript using File APIs
Stack Overflow - jQuery Ajax File Upload to ASP.NET web service with
JSON response
Drag and Drop Asynchronous File Upload <-- DEFINITELY THE MOST
USEFUL
I solved my problem. thank you guys. I used web services. in svc file i wrote these codes:
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service
{
[OperationContract]
public void upload(string data)
{
byte[] base64EncodedBytes = System.Convert.FromBase64String(data);
string strFileDestination = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "somefile.mp3";
File.WriteAllBytes(strFileDestination, base64EncodedBytes);
}
}
in js file i wrote this:
function uploadAudio(mp3Data) {
var reader = new FileReader();
reader.onload = function (event) {
Service.upload(event.target.result, helloWorldCallback, onFail);
function helloWorldCallback(result) {
alert(result);
}
function onFail(e) {
alert(e.get_message);
}
};
reader.readAsDataURL(mp3Data);
}
On a web page, I need to allow users to input the path to a file - which will be stored in a database so I can subsequently display 'a list of documents that apply to this project'.
If I put an input type="file" on the page, it makes it easy for the user to browse to the document ... but, when the form is submitted, the document will be uploaded to the server. I don't want the document, I just want the path.
How would you provide the functionality to allow a user to browse to a file so that you could record the path to the file without actually uploading the file itself?
I just want to end up showing, on a web page, a list of files like:
\myserver\folder20\somefolder\somefile.doc
\myserver2\folder50\somefolder\somefile.doc
I need to give users an easy way to locate those files in the first place - without having to laboriously open Windows Explorer, find the file, and copy and paste the path.
A file upload control gives you access to the path - which is what I need - but I don't want the file uploaded.
I am not very sure if this is what you want.
Assuming that you are selecting the file using input type="file" html control, you will be able to get the complete file path in jquery and pass that to your asp.net code behind using PageMethods (or ajax method of jquery). For this you would need to create a webmethod inside your aspx.cs class.
You can also get the machine name in javascript using any of the following lines of code
Request.ServerVariables["REMOTE_ADDR"]
Request.ServerVariables["REMOTE_HOST"]
Request.ServerVariables["REMOTE_USER"]
I was not able to test these as you have to enable Reverse DNS Lookup for your IIS. You need to search on the net for this.
So, the following steps you would need to do
Your file upload control should look something like this
<input type="file" id="fileSel" />
put a scriptmanager tag, if you dont have one, in your html and set EnablePageMethods to true as
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true"></asp:ScriptManager>
Your javascript should look something like this.
//in javascript
$("document").ready(function () {
$("#fileSel").change(function () {
var val = $get("fileSel").value; // This will give you complete file path i.e. C:\...
alert(val);
PageMethods.SendForm(val, OnSucceeded, OnFailed);//Call to webmethod on server side
//you can also use ajax method but I was not able to make this work
// $.ajax({
// type: "POST",
// //Page Name (in which the method should be called) and method name
// url: "Default.aspx/SendForm",
// // If you want to pass parameter or data to server side function you can try line
// data: "{'fileName':'" + val + "'}",
// //else If you don't want to pass any value to server side function leave the data to blank line below
// // data: "{}",
// contentType: "application/json; charset=utf-8",
// dataType: "json",
// success: function (msg) {
// //Got the response from server and render to the client
// alert(msg.d);
// }
// });
});
});
function OnSucceeded() {
alert("success");
}
function OnFailed(error) {
// Alert user of the error.
alert("failure");
}
The webmethod will be present inside the default.aspx.cs class as
public partial class _Default : System.Web.UI.Page
{
[System.Web.Services.WebMethod]
public static void SendForm(string fileName)
{
//Do your stuff here
}
}
Hope you will be able to solve your problem using the above steps.
Regards,
Samar
If I have an input element like this:
<input type="file" multiple="multiple" name="file1" />
and select multiple files, the browser creates multiple files with the same 'file1' name element. It's like a multiple selection of a listbox.
So how do I capture this in ASP.NET using the Request.Files collection? The Request.Files.AllKeys collection shows all files, but the key values are all the same. Request.Files returns strings for each key but I can only retrieve the first file using the key:
var file = Request.Files["file1"];
This gives me the first file, but I can't access the others also selected in this way since they don't have a unique name. Iteration also doesn't work since Request.Files only returns keys not the actual file entries.
How do I capture these secondary files in ASP.NET?
First, you're right that all keys of the Request.Files collection will be 'file1' (or whatever the name of your input element happens to be).
However you can loop through the collection by index, and retrieve the filename of each upload with the 'Filename' property of each HttpPostedFileBase object.
Each object will also contain an InputStream, and when I debug this in Visual Studio, I can see from the Length property that the stream actually contains the content of each image.
Example:
[HttpPost]
public ActionResult Upload()
{
for (int i = 0; i < Request.Files.Count; i++)
{
Console.WriteLine(Request.Files[i].FileName);
Console.WriteLine(Request.Files[i].InputStream.Length);
}
return View();
}
I guess the ASP.NET team didn't anticipate multi-file uploads. You could probably write an adapter class to convert Request.Files to a collection with a HttpPostedFileWrapper iterator, so you can use a for/each structure.
I'm not sure if you're using MVC, but if so, try this:
[HttpPost]
public ActionResult Upload(HttpPostedFileBase[] files)
{
// Stuff with files
}
Each file will have an InputStream property you can use to get access to the contents.
Also, you'll need to specify the enctype attribute:
<form action="" method="POST" enctype="multipart/form-data">
Hope this helps. I used similar code to handle files coming via this jQuery file upload plugin.
<input id="File1" type="file" runat="server" size="60" multiple="" />
in .cs file HttpFileCollection uploads = HttpContext.Current.Request.Files; for (int i = 0; i < uploads.Count; i++) { HttpPostedFile upload = uploads[i]; Response.Write(#"alert('"+upload.FileName+"');"); }
I think this will may work...