Download a file in FORM POST request C# - c#

I am using C# ASP.NET code and trying to download file on the post request of a form. here is my sample code.
[HttpPost]
public ActionResult PostMethodName(PostModel inputModel)
{
if (ModelState.IsValid)
{
//other code is removed.
//Writing this for the test
//Download Method call
DownloadCertificate("This is the test file to download.");
var statusHtml = RenderViewToString("Status",
new ErrorMsgModel
{
IsSuccess = true,
ErrorDesc = "desc"
});
return Json(new { IsSuccess = true, ErrorDescription =
statusHtml}, JsonRequestBehavior.AllowGet);
}
var statusHtml1 = RenderViewToString("Status",
new ErrorMsgModel
{
IsSuccess = false,
ErrorDesc = "desc"
});
statusHtml1 = statusHtml1.Replace("'", "\\'");
statusHtml1 = statusHtml1.Replace(Environment.NewLine, "");
return Json(new { IsSuccess = false, ErrorDescription = statusHtml1
}, JsonRequestBehavior.AllowGet);
}
Download method which is called from this method.
public ActionResult DownloadCertificate(string content)
{
//Certificate Download
const string fileType = "application/pkcs10";
string fileName = "Certificate" + DateTime.Today.ToString(#"yyyy-MM-dd") + ".csr";
var fileContent = String.IsNullOrEmpty(contrnt) ? "" : contrnt;
byte[] fileContents = Encoding.UTF8.GetBytes(fileContent);
var result = new FileContentResult(fileContents, fileType) { FileDownloadName = fileName };
return result;
}
file download is not working, post functionality is working as desired.

[HttpPost]
public ActionResult DownloadCertificate(PostModel inputModel, string content)
{
if(!ModelState.IsValid){return Json(new {Success=false,//error descr})}
//Certificate Download
const string fileType = "application/pkcs10";
string fileName = "Certificate" + DateTime.Today.ToString(#"yyyy-MM-dd") + ".csr";
var fileContent = String.IsNullOrEmpty(contrnt) ? "" : contrnt;
byte[] fileContents = Encoding.UTF8.GetBytes(fileContent);
var result = new FileContentResult(fileContents, fileType) { FileDownloadName = fileName };
return result;
}
In your previous code you don`t use DownloadCertificate result, you simly execute it.

Your DownloadCertificate method returns a value, but you never use the return value in your PostMethodName method.
Given that you are returning json from that method I would suggest that you return a direct link to the file result in the response. The consuming client can then initiate the download. Something like:
return Json(new { IsSuccess = true, Location = Url.Action("DownloadContent")});
Alternatively you could consider a more restful approach and return a 302 response from the post action:
if (ModelState.IsValid)
{
// you code here
return RedirectToAction("Controller", "DownloadContent", new {content = "myContent"});
}
This may well proceed with the download transparently depending on your client whilst keeping to the Post-Redirect-Get pattern

Related

send image with other attributes to post method in api

I use the code below to send an image to post method and save it as BLOB in DB and it's working successfully:
angular code:
public postUploadedFile(file:any){
this.formData = new FormData();
this.formData.append('file',file,file.name);
this.Url='http://localhost:38300/api/site/PostUploadFiles';
console.log("url passed from here",this.Url)
return this.http.post(this.Url , this.img).subscribe()
}
API code:
public IHttpActionResult PostUploadFiles()
{
int i = 0;
var uploadedFileNames = new List<string>();
string result = string.Empty;
HttpResponseMessage response = new HttpResponseMessage();
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count > 0)
{
while(i < httpRequest.Files.Count && result != "Failed")
{
br = new BinaryReader(httpRequest.Files[i].InputStream);
ImageData = br.ReadBytes(httpRequest.Files[i].ContentLength);
br.Close();
if (DB_Operation_Obj.Upload_Image(ImageData) > 0)
{
result = "success";
}
else
{
result = "Failed";
}
i++;
}
}
else
{
result = "can't find images";
}
return Json(result);
}
but now I need to send more info with image ( type id, name) not just the image, so angular code will be like :
public postUploadedFile(file:any, type_id:number,site_id:number){
this.img = new Image_List();
this.img.images = new Array<PreviewURL>();
this.img.type_id= type_id;
this.img.Reference_id = site_id;
this.img.images.push(file);
this.formData = new FormData();
this.formData.append('file',file,file.name);
this.Url='http://localhost:38300/api/site/PostUploadFiles';
console.log("url passed from here",this.Url)
return this.http.post(this.Url , this.img).subscribe()
}
any help to send and insert in DB.
I think you could just make a single upload file method, and make another method for data insert with the file name,so it will be like:
public postUploadedFile(file:any){ this.formData = new FormData(); this.formData.append('file',file,file.name); this.Url='http://localhost:38300/api/site/PostUploadFiles';
This.newMethod(filename);//and here you upload the other data
console.log("url passed from here",this.Url) return this.http.post(this.Url , this.img).subscribe() }
Use FormData to append additional information to api call.
const formData = new FormData();
formData.append(file.name, file,'some-data');
You can use multiple values with the same name.

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;
}
}

Send file from angular to create new and download from .net

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;

How to get Facebook profile Picture C# .Net

I need to get the user´s facebook profile picture and input it in a crop structure. I´m using Asp.NET MVC, jcrop and the facebook SDK. Untill now i can input files from my computer. I also have a function that access the facebook of the user and returns a session with the user Id, and a GetPhoto function that should return the profile picture. Can someone help me?
I use this code to input the files from the computer:
[ValidateAntiForgeryToken]
public ActionResult _Upload(IEnumerable<HttpPostedFileBase> files)
{
if (files == null || !files.Any()) return Json(new { success = false, errorMessage = "No file uploaded." });
var file = files.FirstOrDefault(); // get ONE only
if (file == null || !IsImage(file)) return Json(new { success = false, errorMessage = "File is of wrong format." });
if (file.ContentLength <= 0) return Json(new { success = false, errorMessage = "File cannot be zero length." });
var webPath = GetTempSavedFilePath(file);
//mistertommat - 18 Nov '15 - replacing '\' to '//' results in incorrect image url on firefox and IE,
// therefore replacing '\\' to '/' so that a proper web url is returned.
return Json(new { success = true, fileName = webPath.Replace("\\", "/") }); // success
}
i tried doing this but the GetPhoto() is returning a null element.
public ActionResult RetornoFb()
{
var _fb = new FacebookClient();
FacebookOAuthResult oauthResult;
if (!_fb.TryParseOAuthCallbackUrl(Request.Url, out oauthResult))
{
// Error
}
if (oauthResult.IsSuccess)
{
dynamic parameters = new ExpandoObject();
parameters.client_id = id;
parameters.redirect_uri = "http://localhost:4323/Avatar/RetornoFb/";
parameters.client_secret = secretkey;
parameters.code = oauthResult.Code;
dynamic result = _fb.Get("/oauth/access_token", parameters);
var accessToken = result.access_token;
Session.Add("FbUserToken", accessToken);
}
else
{
}
//return RedirectToAction("Upload");
HttpPostedFileBase objFile = (HttpPostedFileBase)new MemoryPostedFile(GetPhoto());
var webPath = GetTempSavedFilePath(objFile);
return Json(new { success = true, fileName = webPath.Replace("\\", "/") }); // success
}
public byte[] GetPhoto()
{
try
{
string url = "https://graph.facebook.com/" + GetProfileId() + "?fields=picture.width(480).height(480)";
WebClient webClient = new WebClient();
string response = webClient.DownloadString(url);
dynamic json = JObject.Parse(response);
string urlPicture = json.picture.data.url;
return webClient.DownloadData(urlPicture);
}
catch (Exception)
{
return null;
}
}
Resolved changing my GetPhoto Function. I was having permission issues.
private byte[] GetPhoto()
{
try
{
var _fb = new FacebookClient(Session["FbuserToken"].ToString());
dynamic resultMe = _fb.Get(GetProfileId()+"?fields=picture.width(480).height(480)");
WebClient webClient = new WebClient();
string urlPicture = resultMe.picture.data.url;
return webClient.DownloadData(urlPicture);
}
catch (Exception)
{
return null;
}
}

Categories