Download Excel File with WebAPI/MVC - c#

I am trying to download Excel File through WebAPI. Basically Excel file is created through Memory Stream with the help of this Post
Excel Content is generating fine however I am unable to download the Excel as the Response itself is pure XML when I see it in Response Tab of Chrome Network Tools. Following is my code for C#
var sheet = linq.ExportToExcel(userAddedList);
var stream = new MemoryStream();
var sw = new StreamWriter(stream);
sw.Write(sheet);
sw.Flush();
var result = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ByteArrayContent(stream.GetBuffer()) };
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "Report.xml" };
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/ms-excel");
var response = ResponseMessage(result);
return response;
And this is how I call it through Angular.
var httpRequest = commonFunctions.getRequestObject("GET", requestURL, {}, null);
$http(httpRequest).then(function (response) {
vm.isProcessing = false;
}, function (error) { displayError(error); });

If the browsers you are targeting support the File API you can use the Blob object. Here it is, wrapped in a function, taken from this fiddle:
var setFile = function( data, fileName, fileType ) {
// Set objects for file generation.
var blob, url, a, extension;
// Get time stamp for fileName.
var stamp = new Date().getTime();
// Set MIME type and encoding.
fileType = ( fileType || "text/csv;charset=UTF-8" );
extension = fileType.split( "/" )[1].split( ";" )[0];
// Set file name.
fileName = ( fileName || "ActiveVoice_" + stamp + "." + extension );
// Set data on blob.
blob = new Blob( [ data ], { type: fileType } );
// Set view.
if ( blob ) {
// Read blob.
url = window.URL.createObjectURL( blob );
// Create link.
a = document.createElement( "a" );
// Set link on DOM.
document.body.appendChild( a );
// Set link's visibility.
a.style = "display: none";
// Set href on link.
a.href = url;
// Set file name on link.
a.download = fileName;
// Trigger click of link.
a.click();
// Clear.
window.URL.revokeObjectURL( url );
} else {
// Handle error.
}
};
You would use it as part of your code like this:
$http(httpRequest).then(function (response) {
vm.isProcessing = false;
setFile(response.data, "Report.xls", "application/ms-excel");
}, function (error) { displayError(error); });

Related

Import excel file to angular - "Unexpected token P in JSON at position 0" error

I'm using webapi project in c# and angular
I implemented a function in the controller that exports an excel file, and another funtion in the angular service to import this excel.
The c# funtion works great , it creates a new excel, and saves it into some path.
The problem happens in the angular: Unexpected token P in JSON at position 0
Here is my code:
C# controller:
[HttpGet]
[Route("downloadProducts/{userID}")]
public HttpResponseMessage DownloadProducts(int userID)
{
var pathToExcel=WriteExcel.GetPathToProducts(userID);
var buffer = File.ReadAllBytes(pathToExcel);
var stream = new MemoryStream(buffer);
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(stream.ToArray())
};
result.Content.Headers.ContentDisposition =
new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
FileName = "products.xlsx"
};
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/octet-stream");
return result;
}
Angular service:
downloadFile (userID:number):Observable<Blob>{
return this.http.get<Blob>(`${this.url}/downloadProducts/${userID}`);
}
Componenet.TS
const EXCEL_TYPE = 'application/octet-stream';
this.productsService.downloadloadFile(this.user.userID).subscribe(data=>{
var file = new Blob([data], { type: EXCEL_TYPE });
this.href = window.URL.createObjectURL(file);
setTimeout(() => {
console.log(this.href);
}, 500);
window.open(this.href);
})
What should I fix?
Thanks a lot.
Here in above function use MIME type text/csv instead of application/octet-stream it can download file using .xlsx extension.
Do not convert it to Blob try without it.
downloadFile (userID:number):Observable<any>{
return this.http.get<any>(`${this.url}/downloadProducts/${userID}`);
}

Google Document AI c# mime Unsupported input file format

I am trying to upload a pdf for processing to google's Document AI service. Using google's using Google.Cloud.DocumentAI.V1 for "C#". Looked at the github and docs, not much info. PDF is on the local drive. I converted the pdf to a byte array then converted that to a Bystring. Then set the request mime to "application/pdf" but it return was an error of:
Status(StatusCode="InvalidArgument", Detail="Unsupported input file format.", DebugException="Grpc.Core.Internal.CoreErrorDetailException: {"created":"#1627582435.256000000","description":"Error received from peer ipv4:142.250.72.170:443","file":"......\src\core\lib\surface\call.cc","file_line":1067,"grpc_message":"Unsupported input file format.","grpc_status":3}")
Code:
try
{
//Generate a document
string pdfFilePath = "C:\\Users\\maponte\\Documents\\Projects\\SettonProjects\\OCRSTUFF\\DOC071621-0016.pdf";
var bytes = Encoding.UTF8.GetBytes(pdfFilePath);
ByteString content = ByteString.CopyFrom(bytes);
// Create client
DocumentProcessorServiceClient documentProcessorServiceClient = await DocumentProcessorServiceClient.CreateAsync();
// Initialize request argument(s)
ProcessRequest request = new ProcessRequest
{
ProcessorName = ProcessorName.FromProjectLocationProcessor("*****", "mycountry", "***"),
SkipHumanReview = false,
InlineDocument = new Document(),
RawDocument = new RawDocument(),
};
request.RawDocument.MimeType = "application/pdf";
request.RawDocument.Content = content;
// Make the request
ProcessResponse response = await documentProcessorServiceClient.ProcessDocumentAsync(request);
Document docResponse = response.Document;
Console.WriteLine(docResponse.Text);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
This is the problem (or at least one problem) - you aren't actually loading the file:
string pdfFilePath = "C:\\Users\\maponte\\Documents\\Projects\\SettonProjects\\OCRSTUFF\\DOC071621-0016.pdf";
var bytes = Encoding.UTF8.GetBytes(pdfFilePath);
ByteString content = ByteString.CopyFrom(bytes);
You instead want:
string pdfFilePath = "path-as-before";
var bytes = File.ReadAllBytes(pdfFilePath);
ByteString content = ByteString.CopyFrom(bytes);
I'd also note, however, that InlineDocument and RawDocument are alternatives to each other - specifying either of them removes the other. Your request creation would be better written as:
ProcessRequest request = new ProcessRequest
{
ProcessorName = ProcessorName.FromProjectLocationProcessor("*****", "mycountry", "***"),
SkipHumanReview = false,
RawDocument = new RawDocument
{
MimeType = "application/pdf",
Content = content
}
};

Invalid zip. How can I send a zip file as stream to the client?

My goal is to create a zip file, add a text file to it, save it as stream and send it over to the client where it can download it.
But when I try to download it, I get an invalid zip file but it has at least more and less the correct size. My guess is that I'm doing something completly wrong with the stream on the client-side.
How can I send a zip file as stream to the client?
Controller that sends the zip file :
var zipFile = new ZipFile();
var stream = new MemoryStream();
zipFile.AddFile("path/to/file");
zipFile.Save(stream);
stream.Seek(0, SeekOrigin.Begin);
var httpResponseMessage = new HttpResponseMessage();
httpResponseMessage.Content = new StreamContent(stream);
httpResponseMessage.Content.Headers.Add("zip-filename", "test_originalfile.zip");
httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
httpResponseMessage.Content.Headers.ContentDisposition.FileName = "test_originalfile.zip";
httpResponseMessage.StatusCode = HttpStatusCode.OK;
return httpResponseMessage;
Controller that receives it:
$http.get(applicationServerUrl + '/api/UploadedFiles/GetZip?uploadedFileId=' + uploadedFileId)
.success(function (data, status, headers) {
headers = headers();
var filename = headers['zip-filename'];
var contentType = headers['content-type'];
var linkElement = document.createElement('a');
try {
var blob = new Blob([data], { type: contentType });
var url = window.URL.createObjectURL(blob);
linkElement.setAttribute('href', url);
linkElement.setAttribute("download", filename);
var clickEvent = new MouseEvent("click", {
"view": window,
"bubbles": true,
"cancelable": false
});
linkElement.dispatchEvent(clickEvent);
} catch (ex) {
console.log(ex);
}
}).error(function (data) {
console.log(data);
});

Firefox not downloading properly displayed blob PDF

My clients are unable to download PDF document when trying to save (CTRL+S) a properly displayed PDF document in Firefox (v. 49.0.2) browser.
I dont know if this is my programming problem or a browser problem.
Only way I can download is to click on "Download" button of the PDF plugin, but my clients want to save a file with (CTRL+S) option.
Please take a look at this picture:
And there is a angular code where I try to open a file in browser: it works on Chrome and Edge, it also opens a PDF in Firefox. Response object is a $http response.
function openFile(response) {
var responseHeaders = response.headers();
var contentType = responseHeaders['content-type'];
var contentDisposition = responseHeaders['content-disposition'];
var fileName = contentDisposition.match(/filename="(.+)"/)[1];
fileName = fileName.substring(0, fileName.indexOf(';')-1);
var file = new Blob([response.data], { type: contentType });
if(contentType==='application/pdf') //YES content-type is PDF
{
try
{
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
}
catch(err) //For Edge, just save a file
{
FileSaver.saveAs(file, fileName);
}
}
else //for other content types, just save a file
{
FileSaver.saveAs(file, fileName);
}
}
And this is my C# backend code:
byte[] report = service.GetReportCustomerCreditRatesCard();//render report
RenderFormatResolver renderResolver = new RenderFormatResolver(request.renderFormat);
HttpContent content = new ByteArrayContent(report);
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = content;
response.Content.Headers.ContentType = new MediaTypeHeaderValue(renderResolver.MIMEType);
response.Content.Headers.ContentLength = report.Length;
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") //"attachment", "inline"
{
FileName = String.Format("{0}." + renderResolver.FileNameExtension,
Translations.REPORT_FILENAME_CUSTOMER_CARD),
Name = Translations.REPORT_FILENAME_CUSTOMER_CARD
};
return response;
Try once to change the content disposition header in your response object to hold also the file name:
Content-Disposition: attachment; filename="document.pdf"
So something like:
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue( 'attachment; filename="document.pdf"' );
That might help. Not sure, but worth a try...

Ajax uploading and ASP.NET

I'm trying to upload some text content via ajax, that will be parsed later. That is my Javascript code:
$("#fuFile").change(function () {
var fileInput = document.getElementById("fuFile");
var file = fileInput.files[0];
var formdata = new FormData();
formdata.append('file', file);
var xhr = new XMLHttpRequest();
xhr.open("POST", 'testhandler.ashx', true);
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.setRequestHeader("X-File-Name", file.name);
xhr.setRequestHeader("Content-Type", "application/octet-stream");
xhr.send(formdata);
});
Where fuFile is my file input, and testhandler.ashx is the server handler that gets the uploaded file. (I actually use another handler to parse the file content.)
BUT when I try to do this:
HttpFileCollection fc = context.Request.Files;
It returned no files. But Works in IE for some reason.
But when I try to get the input stream:
StreamReader stream = new StreamReader(context.Request.InputStream);
string text = stream.ReadToEnd();
The text variable become (Http Headers) + File Content.
------WebKitFormBoundaryx16Mw7tnG6JeflIB\r\nContent-Disposition: form-data;name=\"file\"; filename=\"teste export.CSV\"\r\nContent-Type: application/vnd.ms-excel(..file content..)
That's OK, but I've used this plugin: http://valums.com/ajax-upload/
And the plugin returned me only the file content, in witch I could get the content via InputStream, I didn't received any HTTP header.
That's PERFECT, but I want to make a Upload script without using plugins. Just upload and parse, returning some results. Simple and fast
So, My question is: How to get the file content, uploaded by Ajax XHR, getting ONLY the file content, in any browser?
It's work for me and I think it can help you
My js function :
$("#fuFile").click(function () {
var fileInput = document.getElementById("fuFile");
var file = fileInput.files[0];
var fd = new FormData();
fd.append("files", file);
var xhr = new XMLHttpRequest();
xhr.open("POST", 'http://localhost:63186/UploadFile.ashx');
xhr.send(fd);
});
My handler :
string filePath = "~/Files/";
//write your handler implementation here.
if (context.Request.Files.Count <= 0)
{
context.Response.Write("No file uploaded");
}
else
{
for (int i = 0; i < context.Request.Files.Count; ++i)
{
HttpPostedFile file = context.Request.Files[i];
var fileInfo = new FileInfo(file.FileName);
file.SaveAs(context.Server.MapPath(filePath + fileInfo.Name));
context.Response.Write("File uploaded");
}
}

Categories

Resources