Send file from angular to create new and download from .net - c#

I've been trying to download .xml file, but sadly unsuccesfully.
From angular side I am sending *.xml file. In .NET side I take it to process and create a new *.xml file. And I need to download that new file, however I can't really find out how to workaround it.
this is my file-component.ts:
OnSubmit(value, File) {
const params1: FormData = new FormData();
params1.append('File', this.fileToUpload, this.fileToUpload.name);
params1.append('ProcessingMode', value.processingMode);
params1.append('StartDate', value.startDate.formatted);
const params = {
'File': this.fileToUpload,
'ProcessingMode': value.processingMode,
'StartDate': value.startDate.formatted
};
this.mapsConfigurationService.postFile(value, this.fileToUpload, value.startDate.formatted)
.subscribe((res: any) => {
this.downloadFile(res, 'xml'); debugger;
this.xmlProcessing = false;
},
(err) => {
if (err.status === 401) {
// this.router.navigate(['unauthorized']);
} else {
this.xmlProcessing = false;
}
});
downloadFile(data, type) {
const fileName = 'test';
var contentType;
if (type === 'xml') {
contentType = 'text/xml';
}
var blob = new Blob([data._body], { type: contentType });
const dwldLink = document.createElement('a');
const url = URL.createObjectURL(blob);
const isSafariBrowser = navigator.userAgent.indexOf('Safari') !== -1 && navigator.userAgent.indexOf('Chrome') === -1;
if (isSafariBrowser) {
dwldLink.setAttribute('target', '_blank');
}
const fullFileName = fileName + '.' + type;
dwldLink.setAttribute('href', url);
dwldLink.setAttribute('download', fullFileName);
dwldLink.style.visibility = 'hidden';
document.body.appendChild(dwldLink);
dwldLink.click();
document.body.removeChild(dwldLink);}
this is service.ts
postFile(value: any, fileToUpload: File, startDate) {
const formData: FormData = new FormData();
formData.append('File', fileToUpload, fileToUpload.name);
formData.append('ProcessingMode', value.processingMode);
formData.append('StartDate', '2015-05-23');
return this.http
.post(this.Url, formData);
}
and this is backend side:
[HttpPost, DisableRequestSizeLimit]
public ActionResult UploadFile()
{
try
{
var xml = Request.Form.Files["File"].ToString();
var httpRequest = HttpContext.Request.Form;
var postedFile = httpRequest.Files["File"];
string outputFile = Request.Form["info"].ToString();
var startDate = Request.Form["StartDate"];
var file = httpRequest.Files[0];
string fullPath = "";
string folderName = "Upload";
string antFile = #"C:\ant.bat";
string build = #"C:\build.xml";
string rootPath = #"C:\Users";
string newPath = Path.Combine(rootPath, folderName);
if (!Directory.Exists(newPath))
{
Directory.CreateDirectory(newPath);
}
if (file.Length > 0)
{
string fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
fullPath = Path.Combine(newPath, fileName);
using (var stream = new FileStream(fullPath, FileMode.Create))
{
file.CopyTo(stream);
}
}
return PhysicalFile(#"C:\Book1.xml", "application/xml", "Book1.xml");
}
catch (System.Exception ex)
{
return StatusCode(500);
}
}
I get error 500 and I do understand that the problem is with RequestHeaders but I can't figure out the way to solve it and in which side

for downloading for downloading any file... I am use this code in backend
and make and request the code from angular by normal http request
var myFile :: your file
if (System.IO.File.Exists (myFile.Path)) {// to know if the file is Exist or not
//Process File Here ...
} else {
return Json ("NotFound");
}
string contentType = "application/xml";
HttpContext.Response.ContentType = contentType;
var result = new FileContentResult (System.IO.File.ReadAllBytes (myFile.Path), contentType) {
FileDownloadName = $"{myFile.Title }" // + myFile.Extension
};
// System.IO.File.Delete (myFile.Path); //if you want to delete the file after download
return result;

Related

MVC Web Api + ajax to create and download Zip File

I am working on a application that has a button, when that button is clicked it calls a web api GET method. This method takes files and creates a zip folder using System.IO.Compression. This part works great. I see the folder it creates and I am able to open / extract that folder with its files. The problem i have is when the file gets returned to the browser and the browser downloads the file I get the following error: " The Compressed (zipped) folder '...pathToTheDownloadedFile.zip' is invalid. I don't understand what I am doing wrong. All other non-zipped files download and open fine.
Here is my web api GET method:
[HttpGet]
[Route("api/OrderManager/ExtractAllDocuments/{orderNum}/{mappingId}/")]
public HttpResponseMessage ExtractAllDocuments(int orderNum, int mappingId)
{
try
{
var docPath = #"" + HttpContext.Current.Server.MapPath("MyPath");
var files = Directory.GetFiles(docPath);
string zipName = #"supportingdocuments_order" + orderNum + ".zip";
FileStream zipToOpen = new FileStream(docPath + zipName, FileMode.Create);
using (var zipArchive = new ZipArchive(zipToOpen, ZipArchiveMode.Create))
{
foreach (var fPath in files)
{
if (!fPath.Contains(".zip"))
{
zipArchive.CreateEntryFromFile(fPath, Path.GetFileName(fPath), CompressionLevel.Fastest);
}
}
}
zipToOpen.Close();
//At this point the directory is created and saved as it should be
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
var fullZipPath = docPath + zipName;
byte[] bytes = File.ReadAllBytes(fullZipPath);
response.Content = new ByteArrayContent(bytes);
response.Content.Headers.ContentLength = bytes.LongLength;
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = zipName;
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(MimeMapping.GetMimeMapping(zipName));
return response;
}
catch (Exception e)
{
var b = e.Message;
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.NotFound);
response.ReasonPhrase = string.Format("Failed To Extract Files");
throw new HttpResponseException(response);
}
}
Here is my $.ajax call:
$.ajax({
url: 'myApiUrl',
method: 'GET'
}).done(function (data, status, xmlHeaderRequest) {
var downloadLink = document.createElement('a');
var blob = new Blob([data],
{
type: xmlHeaderRequest.getResponseHeader('Content-Type')
});
var url = window.URL || window.webkitURL;
var downloadUrl = url.createObjectURL(blob);
var fileName = '';
// get the file name from the content disposition
var disposition = xmlHeaderRequest.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
fileName = matches[1].replace(/['"]/g, '');
}
}
// Blob download logic taken from: https://stackoverflow.com/questions/16086162/handle-file-download-from-ajax-post
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround for "HTML7007" and "Access Denied" error.
window.navigator.msSaveBlob(blob, fileName);
} else {
if (fileName) {
if (typeof downloadLink.download === 'undefined') {
window.location = downloadUrl;
} else {
downloadLink.href = downloadUrl;
downloadLink.download = fileName;
document.body.appendChild(downloadLink);
downloadLink.click();
}
} else {
window.location = downloadUrl;
}
setTimeout(function () {
url.revokeObjectURL(downloadUrl);
},
100);
}
}).fail(function (data) {
$.notify({
// options
message:
'<i class="fas fa-exclamation-circle"></i> Could not download all documents.'
},
{
// settings
type: 'danger',
placement: {
from: "top",
align: "left"
},
delay: 2500,
z_index: 10031
});
});
I'm at a total and complete loss on this one. Thank you in advance for any help you can provide as it is greatly appreciated.
So after searching I have found a solution that works. $.ajax doesn't like binary data and thinks everything is UTF-8 text encoding apparently. So I used an XMLHttpRequest (xhr). For those that need it below is as copy of the c# and the javascript solution.
C# WebApi Controller:
public HttpResponseMessage ExtractAllDocuments(int orderNum, int mappingId)
{
try
{
var docPath = #"" + HttpContext.Current.Server.MapPath("myPath");
var files = Directory.GetFiles(docPath);
string zipName = #"Supporting-Documents-Order-" + orderNum + ".zip";
FileStream zipToOpen = new FileStream(docPath + zipName, FileMode.Create);
using (var zipArchive = new ZipArchive(zipToOpen, ZipArchiveMode.Create))
{
foreach (var fPath in files)
{
if (!fPath.Contains(".zip"))
{
zipArchive.CreateEntryFromFile(fPath, Path.GetFileName(fPath), CompressionLevel.Fastest);
}
}
}
zipToOpen.Close();
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(new FileStream(docPath + zipName, FileMode.Open, FileAccess.Read));
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = zipName;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
return response;
}
catch (Exception e)
{
var b = e.Message;
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.NotFound);
response.ReasonPhrase = string.Format("Failed To Extract Files");
throw new HttpResponseException(response);
}
}
Front End JavaScript:
function extractAllDocuments() {
let xhr = new XMLHttpRequest();
xhr.addEventListener('readystatechange', function (e) {
if (xhr.readyState == 2 && xhr.status == 200) {
// Download is being started
}
else if (xhr.readyState == 3) {
// Download is under progress
}
else if (xhr.readyState == 4) {
//operation done
// Create a new Blob object using the response data of the onload object
var blob = new Blob([this.response], { type: 'application/zip' });
//Create a link element, hide it, direct it towards the blob, and then 'click' it programatically
let a = document.createElement("a");
a.style = "display: none";
document.body.appendChild(a);
//Create a DOMString representing the blob and point the link element towards it
let url = window.URL.createObjectURL(blob);
a.href = url;
// get the file name from the content disposition
var fileName = '';
var disposition = xhr.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
fileName = matches[1].replace(/['"]/g, '');
}
}
a.download = fileName;
//programatically click the link to trigger the download
a.click();
//Remove From Server
$.ajax({
url: 'myUrl',
method: 'DELETE'
}).done(function (data) {
}).fail(function (data) {
});
setTimeout(function () {
window.URL.revokeObjectURL(url);
}, 60 * 1000);
} else if (xhr.status == 400){
$.notify({
// options
message:
'<i class="fas fa-exclamation-circle"></i> Could not download all documents.'
},
{
// settings
type: 'danger',
placement: {
from: "top",
align: "left"
},
delay: 2500,
z_index: 10031
});
}
});
//set the request type to post and the destination url to '/convert'
xhr.open('GET', 'MyUrl');
//set the reponse type to blob since that's what we're expecting back
xhr.responseType = 'blob';
xhr.send();
return false;
}

Problem with C# Web API export excel file that can not open the file because file format or file extension is not valid

I'm trying to generate excel file from my database and download the file from my website but when I open the excel file the error "can not open the file because file format or file extension is not valid." has occurred.
So, This is my code for doing this.
Here is my script:
$(document).ready(function () {
$("#btnExportExcel").click(function (e) {
e.preventDefault();
const deferred = $.Deferred();
var paymentType = $("#transactionTypeDropdown").val();
var paymentStatus = $("#paymentStatusDropdown").val();
var merchantName = $("#merchantNameDropdown").val();
var dateTime = $("#reservation").val().split(" ");
var refNo = $("#refNoInput").val();
var terminalId = $("#terminalID").val();
$.ajax({
type: "POST",
crossOrigin: true,
url: "/api/Transaction/ExportExcel",
headers: {
Accept: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
},
data: {
"Date_1": dateTime[0],
"Date_2": dateTime[2],
"PaymentType": paymentType,
"Status": paymentStatus,
"Outtrade": refNo,
"Merchant": merchantName,
"TerminalID": terminalId
},
success: function (result) {
if (dateTime[0] == dateTime[2]) {
filename = "Transaction_Detail_" + dateTime[0].replace(/\//g, '-') + ".xlsx";
}
else {
filename = "Transaction_Detail_" + dateTime[0].replace(/\//g, '-') + " - "
+ dateTime[2].replace(/\//g, '-') + ".xlsx";
}
var uri = 'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,' + result;
var link = document.createElement("a");
link.href = uri;
link.style = "visibility:hidden";
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
},
error: function (jqXHR, exception) {
getErrorMessage(jqXHR, exception);
}
});
return deferred.promise();
});
});
Here is my C# API:
public class TransactionController : ApiController
{
[AllowAnonymous]
[HttpPost]
[Route("api/Transaction/ExportExcel")]
public HttpResponseMessage ExportExcel(TransactionSearchReq req)
{
TransactionMgr transaction = new TransactionMgr();
List<TransactionRecordRes> transactionList = new List<TransactionRecordRes>();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
MediaTypeHeaderValue mediaType = MediaTypeHeaderValue.Parse("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
byte[] fileContents;
string fileName;
try
{
// Get transaction records
transactionList = transaction.GetSearchTransactionRecord(req);
if (transactionList.Count() > 0)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
using (var package = new ExcelPackage())
{
var worksheet = package.Workbook.Worksheets.Add("Sheet1");
// I put data to worksheet here.
fileContents = package.GetAsByteArray();
}
if (fileContents == null || fileContents.Length == 0)
{
response = Request.CreateResponse(HttpStatusCode.InternalServerError);
response.Content = new StringContent("Export file error.", Encoding.Unicode);
return response;
}
else
{
if (string.Compare(req.Date_1, req.Date_2) == 0)
{
fileName = string.Format("Transaction_Detail_{0}.xlsx", req.Date_1.Replace('/', '-'));
}
else
{
fileName = string.Format("Transaction_Detail_{0} - {1}.xlsx", req.Date_1.Replace('/', '-'), req.Date_2.Replace('/', '-'));
}
MemoryStream memoryStream = new MemoryStream(fileContents);
response.Content = new StreamContent(memoryStream);
response.Content.Headers.ContentType = mediaType;
response.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment") { FileName = fileName };
return response;
}
}
else
{
response = Request.CreateResponse(HttpStatusCode.InternalServerError);
response.Content = new StringContent("Export file error.", Encoding.Unicode);
return response;
}
}
catch (Exception ex)
{
response = Request.CreateResponse(HttpStatusCode.InternalServerError);
response.Content = new StringContent("Export file error.", Encoding.Unicode);
return response;
}
}
}
Where I'm going wrong ?

Upload file in asp.net and angular 7 null

I upload image from angular to .net core but the file input I receive always null , with the postman , it's receive exactly. I don't know why ?
Can you help me how to solve it?
Thank you so much !
[HttpPost("upload-file")]
public async Task<IActionResult> UploadFile(IFormFile file)
{
try
{
//var file = Request.Form.Files[0];
var rnd = FileHelper.RandomNumber();
//var file = file;
var folder = "Folder";
var index = file.FileName.LastIndexOf('.');
var onlyName = file.FileName.Substring(0, index);
var fileName = onlyName + rnd;
var extension = Path.GetExtension(file.FileName);
var folderThumb = folder + "Thumbnail";
var fileNameThumb = fileName + "Thumbnail";
var t1 = Task.Run(() => FileHelper.SaveFile(folder, fileName, file));
await Task.WhenAll(t1);
var path = new MediaResponseModel()
{
Url = Url.Action("GetFile", "Media", new { folder = folder, fileName = string.Format("{0}{1}", fileName, extension) }, Request.Scheme),
UrlThumbnail = Url.Action("GetFile", "Media", new { folder = folderThumb, fileName = string.Format("{0}{1}", fileNameThumb, extension) }, Request.Scheme),
Title = onlyName
};
return Ok(path);
}
catch (System.Exception e)
{
throw e;
}
}
handleFileInput(files: FileList) {
const file = files.item(0);
this.fileToUpload = {};
this.fileToUpload.data = files.item(0);
this.fileToUpload.fileName = files.item(0).name;
}
onUpload() {
const formData = new FormData();
formData.append('file', this.fileToUpload.data, this.fileToUpload.name);
this.http.post('http://localhost:56000/api/media/upload-file', formData).subscribe(res => console.log(res));
}

How to get the text from the POST request in C#

I have a simple form on Angular , where I upload a file and a description.
constructor(private http: HttpClient) { }
upload(files) {
if (files.length === 0)
return;
const formData: FormData = new FormData();
var filedesc = this.description;
for (let file of files) {
formData.append(file.name, file);
formData.append("Description", filedesc);
}
const uploadReq = new HttpRequest('POST', `api/upload`, formData, {
reportProgress: true,
});
In the controller, I get only the file name.
[HttpPost, DisableRequestSizeLimit]
public ActionResult UploadFile()
{
try
{
var fileContent = Request.Form.Files[0];
string folderName = "Upload";
var contenttype = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
string webRootPath = _hostingEnvironment.WebRootPath;
string newPath = Path.Combine(webRootPath, folderName);
if (!Directory.Exists(newPath))
{
Directory.CreateDirectory(newPath);
}
if (fileContent.Length > 0)
{
if (fileContent.ContentType == contenttype)
{
string fileName = ContentDispositionHeaderValue.Parse(fileContent.ContentDisposition).FileName.Trim('"');
string fullPath = Path.Combine(newPath, fileName);
using (var stream = new FileStream(fullPath, FileMode.Create))
{
fileContent.CopyTo(stream);
}
}
else
{
return Json("Wrong File Type.");
}
My question is how to receive description string in this case? Or is it bad that I append file and description in one request?
Like said Aman B before, add a parameter and use this code
foreach (string key in Request.Form.Keys)
{
description = key;
}
You have to add a parameter to your action method to receive the description:
//If you are expecting a single file description
public ActionResult UploadFile(string description)
{
//Logic..
}
//If you are expecting multiple file descriptions
public ActionResult UploadFile(IEnumerable<string> description)
{
//Logic..
}
It is ok to send form data with files in the same request. This is what the "multipart/form-data" content-type header is used for.

Download file on button click

I have a application where a button click needs to download a text log file. I wrote the backend API, but am not able to connect it from the frontend button click. Working on Angular 2 and C#. What changes do I need to make to component.ts file?
Button code:
<div class="col-lg-4"> <button type="button" class="btn btn-info pull-right" [hidden]="!dbtn" (click)="GetMigrationLog()" id="downloadLog" translate>Download Log</button> </div>
Here is my backend api code:
[Route("GetMigrationLog")]
public IHttpActionResult GetMigrationLog()
{
try
{
IDBMigrationDataBo data = _serviceLocator.Resolve<IDBMigrationDataBo>();
var result = data.GetMigrationLog();
string logFileName = string.Format("Migration_{0}.txt", DateTime.Now.ToString("dd-MM-yyyy"));
return StreamResponse(result, logFileName);
}
catch (Exception ex)
{
logger.Error(ex.Message);
return this.HandleError(ex);
}
}
I've done somthing similar .. it's a little bit difficult .. i share my experience and my code with you .. hope it helps you!!
in your html
Download Log
in your ts:
saveFile(id: string, name: string) {
this._orderService.DownloadRicetta(id, name).then((result) => {
this._toaster.pop('success', 'Download', 'Ricetta Scaricata con Successo');
}).catch((err) => {
this._toaster.pop('error', 'Download', 'Errore nel Download della Ricetta!')
console.log(err);
});
}
in your service file:
first of all import a package (installed with npm i --save file-saver #types/file-saver)
import * as FileSaver from 'file-saver';
then write your method like this:
public async DownloadRicetta(id: string, name: string): Promise<Blob> {
return new Promise<Blob>((resolve, reject) => {
const headers = new HttpHeaders();
headers.append('Accept', 'text/plain'); //just check the type you need
this._http.get(environment.API_URL + `Order/${id}/Download/Ricetta`, { headers: headers, responseType: "blob", observe: 'response' })
.subscribe(response => {
try {
let blob = this.saveToFileSystem(response, name);
resolve(blob);
} catch (error) {
reject(error);
}
});
});
}
private saveToFileSystem(response, name: string): Blob {
const contentDispositionHeader: string = response.headers.get('Content-Disposition');
//for get original filename
const parts: string[] = contentDispositionHeader.split(';');
const filename = parts[1].trim().split('=')[1].trim();
//get extension of the file
const parts2: string[] = contentDispositionHeader.split('.');
let ext = parts2[1];
ext = ext.replace('"', '')
//set mimetype
let mimeType = Utils.extToMimeType(ext);
const blob = new Blob([response.body], { type: mimeType });
FileSaver.saveAs(blob, name + '_ricetta.' + ext);
return blob;
}
file UTILS.ts:
export default class Utils {
static extToMimeType(ext: string) {
switch (ext) {
case "pdf":
return "application/pdf";
case "jpg":
return "image/jpg";
case "png":
return "image/png";
case "txt":
return "text/plain";
default:
return "";
}
}
}
AND ALSO BACK END (ASP.NET WEBAPI 2 ):
[HttpGet]
[Route("api/Order/{id}/Download/Ricetta")]
public async Task<HttpResponseMessage> GetBookForHRM([FromUri] string id)
{
try
{
if (string.IsNullOrEmpty(id)) return new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest };
var order = await _orderService.FindAsync(xx => xx.Id == id);
if (order == null) return new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest };
if (string.IsNullOrEmpty(order.RicettaUrl)) return new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest };
var user = await _aspNetService.FindAsync(xx => xx.Id == order.IdUser);
if (user == null) return new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest };
var fileWithPath = $#"{user.GetUserRicettaDirectory()}/{order.RicettaUrl}";
//converting Pdf file into bytes array
var dataBytes = File.ReadAllBytes(fileWithPath);
//adding bytes to memory stream
var dataStream = new MemoryStream(dataBytes);
HttpResponseMessage httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK);
httpResponseMessage.Content = new StreamContent(dataStream);
httpResponseMessage.Content.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
httpResponseMessage.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
FileName = order.RicettaUrl.Trim()
};
httpResponseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
return httpResponseMessage;
}
catch (Exception ex)
{
_logger.LogException(ex);
throw;
}
}

Categories