send image with other attributes to post method in api - c#

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.

Related

uploading and accessing images into asp .net api folder using angular

I have angular project as my client side and .Net 6 web api project as my backend. I am still new to both technologies. I am creating a website and there is a functionality that I am trying to add and haven't been successful so far. I want to upload images into a .Net web api project images folder using angular. I also want to later access those images from angular project. I want to store the path of the image files in the database. I have tried to check for the code on the internet without success. Your assistance will be appreciated.
First, submit your's files from frontend with FormData
postWithFile(url: string, obj: any, files: File[]) {
let cloneHeader: any = {};
let options: any = {
headers: new HttpHeaders(cloneHeader),
observe: 'response',
responseType: 'json'
};
let formData: FormData = new FormData();
if (typeof obj == 'object') { // obj is external submit data
formData.append('data', JSON.stringify(obj));
} else {
formData.append('data', obj);
}
if (files && files.length > 0) {
files.forEach((ds, index) => {
formData.append('file_' + index, ds, ds.name);
});
}
return this._http
.post(this.host + url, formData, options)
.pipe(map((res: any) => {
return res.body;
}));
}
And backend handle request with HttpContext.Current.Request.Files, save images to server and store path of images in database
[HttpPost]
public ResponseMessage<bool?> UploadImages()
{
var response = new ResponseMessage<bool?>();
try
{
if (!Request.Content.IsMimeMultipartContent())
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
ExternalDataModel model = MessageConvert.DeserializeObject<ExternalDataModel>(HttpContext.Current.Request["data"]); // obj in frontend
//
List<string> listImages = new List<string>();
DateTime now = DateTime.Now;
string buildPath = $"{string.Format("{0:00}", now.Year)}\\{string.Format("{0:00}", now.Month)}\\{string.Format("{0:00}", now.Day)}"; // change by your's folder path
foreach (string file in HttpContext.Current.Request.Files)
{
var fileContent = HttpContext.Current.Request.Files[file];
int fileLength = fileContent.ContentLength;
if (fileContent != null && fileLength > 0)
{
var stream = fileContent.InputStream;
byte[] imgByteArray;
using (MemoryStream memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
imgByteArray = memoryStream.ToArray();
}
string fileName = $"format_file_name_if_need_{fileContent.FileName}";
string RelativeFolder = $"{buildPath}";
string AbsoluteFolder = Path.Combine("FOLDER_IN_SERVER_FULL_PATH", RelativeFolder);
if (!Directory.Exists(AbsoluteFolder))
{
Directory.CreateDirectory(AbsoluteFolder);
}
string pathSave = Path.Combine(RelativeFolder, fileName);
FileHelper.SaveFileFromBinaryArray(pathSave, imgByteArray);
listImages.Add(pathSave);
}
}
// model.listImages = listImages; // assign to model to save to DB
//
// var data = _bus.uploadImage(model);
// if (data)
// {
// response.Data = true;
// response.MessageCode = MessageCodes.UpdateSuccessfully;
// }
}
catch (Exception ex)
{
response.MessageCode = ex.Message;
}
return response;
}

InvalidOperationException in Memory Streams

I am trying to upload an image to cloudinary cloud. The file converts fine to memory stream but when I try to call upload method of cloudinary to upload the image, I get InvlalidOperationException. What I think is, there is something wrong with converting file to stream.See the image showing error
[HttpPost]
public async Task<IActionResult> AddPhotoForUser(int userId, [FromForm] AddPhotoDto addPhotoDto)
{
try
{
if (userId != int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value))
{
return Unauthorized();
}
var userFromRepo = await _datingRepository.GetUser(userId);
var file = addPhotoDto.File;
var uploadResult = new ImageUploadResult();
if (file.Length > 0)
{
using (var stream = file.OpenReadStream())
{
var uploadParams = new ImageUploadParams()
{
File = new FileDescription(file.Name, stream),
Transformation = new Transformation()
.Width(500).Height(500).Crop("fill").Gravity("face")
};
uploadResult = _cloudinary.Upload(uploadParams);
}
}
addPhotoDto.Url = uploadResult.Url.ToString();
addPhotoDto.PublicId = uploadResult.PublicId;
var photo = _mapper.Map<Photo>(addPhotoDto);
if (!userFromRepo.Photos.Any(p => p.IsMain))
{
photo.IsMain = true;
}
userFromRepo.Photos.Add(photo);
if (await _datingRepository.SaveAll())
{
var photoToReturn = _mapper.Map<ReturnPhotoDto>(photo);
return CreatedAtRoute("GetPhoto", new { id = photo.Id }, photoToReturn);
}
return BadRequest("Could not add photo");
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
Can you please share why do you use open stream? You can try:
var imageuploadParams = new ImageUploadParams () {
File = new FileDescription (#"https://res.cloudinary.com/demo/image/upload/v1561532539/sample.jpg"),
PublicId = "myimage",
Transformation = new Transformation().Width(500).Height(500).Crop("fill").Gravity("face")
};
var ImageuploadResult = cloudinary.Upload (imageuploadParams);

Download a file in FORM POST request 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

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

Mock Web API HTTPResponseMessage C# Unit Testing

I want to create a unit test method for the below method which is receiving a file upload "text file" data and parsing it, I tried to use Moq and created a method but I am still very confused in the concept, I need a sample code, I've read many stackover flow questions but it is all for Controllers not Web API
the method used
// Enable both Get and Post so that our jquery call can send data, and get a status
[HttpGet]
[HttpPost]
public HttpResponseMessage Upload()
{
// Get a reference to the file that our jQuery sent. Even if multiple files, they will
// all be their own request and be the 0 index
if (HttpContext.Current.Request.Files.Count>0)
{
HttpPostedFile file = HttpContext.Current.Request.Files[0];
if (file != null && file.ContentLength > 0)
{
try
{
var extension = Path.GetExtension(file.FileName);
if (!IsFileFormatSupported(extension))
{
var objectSerialized = SerializeData(GetError( GlobalResources.NotSupportedFileExtension));
return BadResponse(objectSerialized);
}
var path = SaveFileGetPath(file);
var result = GetPaySlips(path);
var SerializedData = SerializeData(result);
return OkResponse(SerializedData);
}
catch (System.Exception exception)
{
var SerializedData = SerializeData(GetError( GlobalResources.CouldNotReadFile + " " + exception.Message));
return BadResponse(SerializedData);
}
}
else
{
var SerializedData = SerializeData(GetError(file.FileName + " " + GlobalResources.FileisCorrupt));
return BadResponse(SerializedData);
}
}else
{
var SerializedData = SerializeData(GetError( GlobalResources.FileisCorrupt));
return BadResponse(SerializedData);
}
}
the code I did so far
var FileUploadCtrl = new UploadController();
Mock<HttpRequestMessage> cc = new Mock<HttpRequestMessage>();
UTF8Encoding enc = new UTF8Encoding();
// Mock<HttpPostedFileBase> file1 = new Mock<HttpPostedFileBase>();
//file1.Expect(f=>f.InputStream).Returns(file1.Object.InputStream);
//cc.Expect(ctx => ctx.Content).Returns(new retur);
// cc.Expect(ctx => ctx.Content).Returns();
var content = new ByteArrayContent( /* bytes in the file */ );
content.Headers.Add("Content-Disposition", "form-data");
var controllerContext = new HttpControllerContext
{
Request = new HttpRequestMessage
{
Content = new MultipartContent { content }
}
};
//file1.Expect(d => d.FileName).Returns("FileTest.csv");
//file1.Expect(d => d.InputStream).Returns(new HttpResponseMessage(HttpStatusCode.OK)));
var config = new HttpConfiguration();
//var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/upload");
var route = config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}");
var routeData = new HttpRouteData(route, new HttpRouteValueDictionary { { "controller", "FileUpload" } });
FileUploadCtrl.ControllerContext = new HttpControllerContext(config, routeData, cc.Object);
var r = FileUploadCtrl.Upload();
Assert.IsInstanceOfType(r, typeof(HttpResponseMessage));

Categories