I'm getting this error when trying to upload a file to webapi
Unable to cast object of type 'System.String' to type 'System.Web.HttpPostedFile'
javascript:
UploadReceivingIssueImages(e) {
if (!e.target.files || e.target.files.length === 0)
return;
let formData = new FormData();
for (var i = 0; i < e.target.files.length; i++) {
formData.append('file', e.target.files[i]);
}
var vm = this;
axios.post('../api/receiving/UploadDocReceivingIssueImages?headerId=' + this.SelectedSubIdIdObj.HeaderId,
formData,
{
headers: {
'Content-Type': 'multipart/form-data'
}
}
).then(function () {
vm.getDocReceivingIssueImages();
console.log('SUCCESS!!');
}, function (er) {
alert("Couldn't upload images")
});
}
WebApi Code
[HttpPost]
public bool UploadDocReceivingIssueImages([FromUri] int headerId)
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count < 1)
{
var resp = new HttpResponseMessage(HttpStatusCode.NotFound)
{
Content = new StringContent("No File Uploaded"),
ReasonPhrase = "No File Uploaded"
};
throw new HttpResponseException(resp);
}
var dirPath = #"\\dirPath";
foreach (var f in httpRequest.Files)
{
var pf = (System.Web.HttpPostedFile)f;
pf.SaveAs(dirPath + Guid.NewGuid().ToString() + pf.FileName);
}
return true;
}
the error happens at
var pf = (System.Web.HttpPostedFile)f;
the f object is a string with value 'file'... WHY?!?!
any help would be appreciated.
Because when you enumerate over HttpRequest.PostedFiles you're enumerating over its keys (the names, which are all 'file' based on your JS), not the files:
foreach (var key in httpRequest.Files)
{
var pf = httpRequest.Files[key]; // implicit cast to HttpPostedFile
pf.SaveAs(dirPath + Guid.NewGuid().ToString() + pf.FileName);
}
EDIT TO ADD:
With that said, you'll need to update your JS to use unique names in FormData or else you'll only be able to read one file out of your HttpContext's HttpFileCollection:
for (var i = 0; i < e.target.files.length; i++) {
formData.append('file' + i, e.target.files[i]);
}
See HttpFileCollection on MSDN
Related
I want to download all audio files from folder but this code only download last file in folder.
var element = document.getElementById("songs");
var audionum = element.getElementsByTagName('audio').length;
var zipcounter = 0;
var zip = new JSZip();
var zipName = 'Test.zip';
for(var i = 0; i < audionum; i++){
var audiosrc = document.getElementsByTagName('source')[i].getAttribute("src");
var audiosrcsplit = audiosrc.split('/')[1];
// loading a file and add it in a zip file
JSZipUtils.getBinaryContent(audiosrc, function (err, data) {
if(err) {
throw err; // or handle the error
}
zip.file(audiosrcsplit, data, {binary:true});
zipcounter++;
if (zipcounter == audionum) {
zip.generateAsync({type:'blob'}).then(function(content) {
saveAs(content, zipName);
});
}
});
}
For ES6 , you can try replacing var with let (block scope).
If you are making use of ES5 then, try something like below.
var element = document.getElementById("songs");
var audionum = element.getElementsByTagName('audio').length;
var zipcounter = 0;
var zip = new JSZip();
var zipName = 'Test.zip';
function addToZip(audiosrc, audiosrcsplit) {
JSZipUtils.getBinaryContent(audiosrc, function (err, data) {
if (err) {
throw err; // or handle the error
}
zip.file(audiosrcsplit, data, {
binary: true
});
zipcounter++;
if (zipcounter == audionum) {
zip.generateAsync({
type: 'blob'
}).then(function (content) {
saveAs(content, zipName);
});
}
});
}
for (var i = 0; i < audionum; i++) {
var audiosrc = document.getElementsByTagName('source')[i].getAttribute("src");
var audiosrcsplit = audiosrc.split('/')[1]; // loading a file and add it in a zip file
addToZip(audiosrc, audiosrcsplit);
}
I am trying to upload large binary files from a web client to a .NET 4.6.1 Framework MVC API. These files could range anywhere from 5GB to 20GB.
I have tried splitting the file into chunks to upload each chunk and merge the results at the end, but the merged file is always corrupted. If I work with small files and don't split, the binary will work correctly. However, when I split and merge the file is "corrupted". It won't load or behave as expected.
I have looked all over and haven't seen a proper solution to this so i'm hoping someone can help me here.
I followed this https://forums.asp.net/t/1742612.aspx?How+to+upload+a+big+file+in+Mvc, but I can't get it to work and the corrected solution was never posted. I am keeping track of the order of files before merging on the server.
Javascript (Call to uploadData is made to initiate)
function uploadComplete(file) {
var formData = new FormData();
formData.append('fileName', file.name);
formData.append('completed', true);
var xhr3 = new XMLHttpRequest();
xhr3.open("POST", "api/CompleteUpload", true); //combine the chunks together
xhr3.send(formData);
return;
}
function uploadData(item) {
var blob = item.zipFile;
var BYTES_PER_CHUNK = 750000000; // sample chunk sizes.
var SIZE = blob.size;
//upload content
var start = 0;
var end = BYTES_PER_CHUNK;
var completed = 0;
var count = SIZE % BYTES_PER_CHUNK == 0 ? SIZE / BYTES_PER_CHUNK : Math.floor(SIZE / BYTES_PER_CHUNK) + 1;
while (start < SIZE) {
var chunk = blob.slice(start, end);
var xhr = new XMLHttpRequest();
xhr.onload = function () {
completed = completed + 1;
if (completed === count) {
uploadComplete(item.zipFile);
}
};
xhr.open("POST", "/api/MultiUpload", true);
xhr.setRequestHeader("contentType", false);
xhr.setRequestHeader("processData", false);
xhr.send(chunk);
start = end;
end = start + BYTES_PER_CHUNK;
}
}
Server Controller
//global vars
public static List<string> myList = new List<string>();
[HttpPost]
[Route("CompleteUpload")]
public string CompleteUpload()
{
var request = HttpContext.Current.Request;
//verify all parameters were defined
var form = request.Form;
string fileName;
bool completed;
if (!string.IsNullOrEmpty(request.Form["fileName"]) &&
!string.IsNullOrEmpty(request.Form["completed"]))
{
fileName = request.Form["fileName"];
completed = bool.Parse(request.Form["completed"]);
}
else
{
return "Invalid upload request";
}
if (completed)
{
string path = HttpContext.Current.Server.MapPath("~/Data/uploads/Tamp");
string newpath = Path.Combine(path, fileName);
string[] filePaths = Directory.GetFiles(path);
foreach (string item in myList)
{
MergeFiles(newpath, item);
}
}
//Remove all items from list after request is done
myList.Clear();
return "success";
}
private static void MergeFiles(string file1, string file2)
{
FileStream fs1 = null;
FileStream fs2 = null;
try
{
fs1 = System.IO.File.Open(file1, FileMode.Append);
fs2 = System.IO.File.Open(file2, FileMode.Open);
byte[] fs2Content = new byte[fs2.Length];
fs2.Read(fs2Content, 0, (int)fs2.Length);
fs1.Write(fs2Content, 0, (int)fs2.Length);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + " : " + ex.StackTrace + " " + file2);
}
finally
{
if(fs1 != null) fs1.Close();
if (fs2 != null)
{
fs2.Close();
System.IO.File.Delete(file2);
}
}
}
[HttpPost]
[Route("MultiUpload")]
public string MultiUpload()
{
try
{
var request = HttpContext.Current.Request;
var chunks = request.InputStream;
string path = HttpContext.Current.Server.MapPath("~/Data/uploads/Tamp");
string fileName = Path.GetTempFileName();
string newpath = Path.Combine(path, fileName);
myList.Add(newpath);
using (System.IO.FileStream fs = System.IO.File.Create(newpath))
{
byte[] bytes = new byte[77570];
int bytesRead;
while ((bytesRead = request.InputStream.Read(bytes, 0, bytes.Length)) > 0)
{
fs.Write(bytes, 0, bytesRead);
}
}
return "test";
}
catch (Exception exception)
{
return exception.Message;
}
}
I'm generating an excel file in my MVC controller using EPPLUS.
And I'm invoking the controller method from angular js controller using a ajax request
$scope.agreedFlow = function () {
var ajaxexcelDownload = AgreedFlowService.GenerateAgreedFlow({
});
$q.all([ajaxexcelDownload]).then(function (responses) {
});
};
And my angular service
self.GenerateAgreedFlow = function (data, callback) {
ajaxService.post({
url: '/Plan/GenerateAgreedFlow'
, data: data
, dataType: 'json'
, responseType: 'arraybuffer'
, cache: false
}).done(function (result) {
if (typeof callback === "function")
callback(result);
}).fail(function () {
});
};
And my MVC Controller method
public void GenerateAgreedFlow()
{
var planService = ServiceFactory.PlanService;
var fileName = "ExcellData.xlsx";
var file = new FileInfo( fileName);
using (var package = new OfficeOpenXml.ExcelPackage(file))
{
// add a new worksheet to the empty workbook
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("AgreedPlan " + DateTime.Now.ToShortDateString());
// --------- Data and styling goes here -------------- //
DataTable dt =planService.GetAgreedYarnFlow();
int iCol = 1;
// Add column headings...
foreach (DataColumn c in dt.Columns)
{
worksheet.Cells[1, iCol].Value = c.ColumnName;
worksheet.Cells[1, iCol].Style.Fill.PatternType = ExcelFillStyle.Solid;
worksheet.Cells[1, iCol].Style.Fill.BackgroundColor.SetColor(Color.LightGray);
iCol++;
}
for (int j = 0; j < dt.Rows.Count; j++)
{
for (int k = 0; k < dt.Columns.Count; k++)
{
worksheet.Cells[j + 2, k + 1].Value = dt.Rows[j].ItemArray[k].ToString();
if (int.Parse(dt.Rows[j].ItemArray[7].ToString()) == 1)
{
worksheet.Cells[j + 2, k + 1].Style.Locked = false;
worksheet.Cells[j + 2, k + 1].Style.Fill.PatternType = ExcelFillStyle.Solid;
worksheet.Cells[j + 2, k + 1].Style.Fill.BackgroundColor.SetColor(Color.LightBlue);
}
}
var colCount = dt.Columns.Count;
}
worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns();
worksheet.Column(1).Hidden = true;
worksheet.Column(2).Hidden = true;
worksheet.Column(3).Hidden = true;
worksheet.Column(4).Hidden = true;
worksheet.Column(5).Hidden = true;
worksheet.Column(8).Hidden = true;
worksheet.Protection.IsProtected = true;
// save our new workbook and we are done!
package.Workbook.Properties.Title = "Attempts";
this.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
this.Response.AddHeader(
"content-disposition",
string.Format("attachment; filename={0}", "ExcellData.xlsx"));
this.Response.BinaryWrite(package.GetAsByteArray());
}
Is there any way to download file from the ajax response ??
I am using Kendo UI uploader. When I upload the files using kendoUpload, actually I rename the files using Guid.NewGuid() in server side. The problem is that, when I want to remove the files, the original file name is sent to remove handler in server side instead of guidName. How can I solve this issue?
My remove handler in server side is as follows:
[HttpPost]
public ActionResult RemoveTemp(string[] fileNames)
{
List<string> removedFiles = new List<string>();
string tempPath = Server.MapPath("~/temp/");
if (fileNames != null)
{
foreach (var fullName in fileNames)
{
File.Delete(tempPath + fullName);
removedFiles.Add(fullName);
}
}
return Json(removedFiles.ToArray());
}
My remove event in client side is as follows:
remove: function (e) {
var fileToRemove = e.files[0].name;
for (var i = 0; i < vm[item].length; i++) {
if (vm[item][i].originalName == fileToRemove) {
vm[item].splice(i, 1);
break;
}
}
// I don't know how to send guidNames here using e.data
}
You need to include the name of the saved files in the upload response, and at the client, set the name of the e.files accordingly.
Sample upload action:
[HttpPost]
public ActionResult UploadFiles()
{
// Note: We use Request.Files instead of a parameter input, to be independent of the name of the Kendo upload component
var count = Request.Files.Count;
if (count == 0)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
var result = new List<UploadedFile>(count);
for (var i = 0; i < count; i++)
{
HttpPostedFileBase file = Request.Files[i];
if (file == null || (file.ContentLength == 0 && string.IsNullOrEmpty(file.FileName)))
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
// Some browsers send file names with full path. We are only interested in the file name.
var fileName = Path.GetFileName(file.FileName);
var tempKey = _svcUpload.SaveTempFile(file.InputStream, fileName);
result.Add(new UploadedFile
{
TempKey = tempKey,
Name = fileName,
Extension = Path.GetExtension(file.FileName),
Size = file.ContentLength
});
}
return Json(result);
}
_svcUpload.SaveTempFile() saves an uploaded file and returns its temp key (which can be the GUID of your renamed file). We include the temp key, along with other file info, in the response.
Here is the client-side upload-success handler:
function fileUploadSuccess(e) {
if (e.operation === 'upload') {
for (var i = 0; i < e.response.length; i++) {
var tempKey = e.response[i].TempKey;
e.files[i].name = tempKey;
}
}
}
function deleteFiles(fileId,supportsTeamDrives) {
var date = new Date();
date.setDate(date.getDate() - 180);
var n = date.toISOString().split('.')[0] ;
var test = false;
gapi.client.drive.files.list({
pageSize: x,
q: "starred = "+test+" and viewedByMeTime < '"+n+"'",
orderBy: 'quotaBytesUsed desc',
fields: "nextPageToken, files(id, name, viewedByMeTime, mimeType, quotaBytesUsed)",
}
)
.then(function(response) {
var files = response.result.files;
if (files && files.length > 0) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var file_id = file.id,
)');
}}
var request = gapi.client.drive.files.delete({
supportsTeamDrives: 'false',
fileId: file_id ,
}); }
request.execute(function(resp) { });
}
I want this function to list out the fileIDs, as as each fileID is put out, they get deleted. How do I combine list file and delete file functions together for this to work?
Currently I separated them into two functions, but the variable fileID only saves the last fileID outputted, thus, the delete function would only delete one file, the last file listed. I want it to list and output every file to a varable and as its listed it gets deleted. What can I change or add in my goal to accomplish this?
You can alter your code to delete the file in your loop:
function deleteFiles(fileId, supportsTeamDrives) {
var date = new Date();
date.setDate(date.getDate() - 180);
var n = date.toISOString().split('.')[0];
var test = false;
gapi.client.drive.files.list({
pageSize: x,
q: "starred = " + test + " and viewedByMeTime < '" + n + "'",
orderBy: 'quotaBytesUsed desc',
fields: "nextPageToken, files(id, name, viewedByMeTime, mimeType, quotaBytesUsed)",
}
)
.then(function(response) {
var files = response.result.files;
if (files && files.length > 0) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var file_id = file.id;
deleteFile(file_id);
}
}
});
}
// method used to delete the files
function deleteFile(file_id) {
var request = gapi.client.drive.files.delete({
supportsTeamDrives: 'false',
fileId: file_id,
});
request.execute(function(resp) {});
}