I need little help to modify my function. How can I check if the file already exists with the same name? and if it does then to add a newguid string to the name and save the new file.
public string UploadStorageFile(StorageModel newFile, int userId)
{
string uniqueFileName = null;
if(newFile.FileName != null)
{
string uploadsFolder = Path.Combine(_webHostEnvironment.WebRootPath, $"repositories/{userId}");
if (!Directory.Exists(uploadsFolder))
{
Directory.CreateDirectory(uploadsFolder);
}
uniqueFileName = Guid.NewGuid().ToString() + "_" + newFile.FileName.FileName;
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
using(var fileStream = new FileStream(filePath, FileMode.Create))
{
newFile.FileName.CopyTo(fileStream);
}
}
return uniqueFileName;
}
For Checking, if a File already exists, you can use the File.Exists() method.
Here is a basic example, on how to check if a File does already exist:
public bool DoesFileAlreadyExist(string uploadFolder, string fileName)
{
var file = $"{uploadFolder}\{fileName}";
return File.Exists(file);
}
Specific on your Code, you could use the method like in this example (Just call the method, and check if it is existing):
public string UploadStorageFile(StorageModel newFile, int userId)
{
string uniqueFileName = null;
if(newFile.FileName != null)
{
string uploadsFolder = Path.Combine(_webHostEnvironment.WebRootPath, $"repositories/{userId}");
if (!Directory.Exists(uploadsFolder))
{
Directory.CreateDirectory(uploadsFolder);
}
if (!DoesFileAlreadyExist(uploadsFolder, newFile.Filename)
{
uniqueFileName = Guid.NewGuid().ToString() + "_" + newFile.FileName.FileName;
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
using(var fileStream = new FileStream(filePath, FileMode.Create))
{
newFile.FileName.CopyTo(fileStream);
}
}
return uniqueFileName;
}
return "NO FILE CREATED";
}
Related
My Project is in ASP.NET MVC, Right now I am using Razor Engine Service (RazorEngineService.RunCompile) to create multiple XML files and making it as a single Zip file and exporting it.
But the problem is that when we pass the model object each time to process the template and return it as separate XML files and completing the whole operation it takes more time to complete (Almost ~40 Seconds for 10 objects) for whole content to export.
Is there anything wrong with my current approach or am I doing it correctly right now? Please guide me If I am doing any mistakes in this approach.
private FileInfo Export(List<Model> modelList)
{
string timeStr = Datetime.Now.ToString();
string archiveFileName = "Main.zip";
string archivePath = Path.Combine(_reportFolderPath, archiveFileName);
using (ZipArchive archive = ZipFile.Open(archivePath, ZipArchiveMode.Create))
{
foreach (var list in modelList)
{
string fileName = model.name + model.Id;
string filePath = GetModelExport(list, fileName, timeStr);
archive.CreateEntryFromFile(filePath, fileName + ".xml");
}
archive.Dispose();
}
return new FileInfo(archivePath);
}
private string GetModelExport(Model model, string fileName, string timeStr)
{
var processedTemplate = ProcessTemplate(model, TemplateName, TemplateKey);
string reportFilelName = fileName + "_" + timeStr + ".xml";
string filePath = Path.Combine(_reportFolderPath, reportFilelName);
using (var file = new StreamWriter(filePath))
{
file.Write(processedTemplate);
}
return filePath;
}
private string ProcessTemplate(Model model, string templateName, string templateKey)
{
var templateFilePath = Path.Combine(_reportTemplateFolder, templateName);
return ReportUtils.ProcessTemplate(templateFilePath, templateKey, model);
}
public static string ProcessTemplate(string templatePath, string templateKey, object model = null)
{
var templateService = RazorEngineService.Create();
var result = templateService.RunCompile(File.ReadAllText(templatePath), templateKey, null, model);
return result;
}
some of your code is missing so i cant see the whole picture, this is what i would start with..... gd luck.
public class HolderTempName
{
private TemplateService _templateService;
private Dictionary<string, string> _templateContainer;
public HolderTempName()
{
//this will save creating this everytime
_templateService = RazorEngineService.Create();
//this will hold the template so it does not have to fetch on each loop,
//if the same template is used.
_templateContainer = new Dictionary<string, string>();
}
//you will need to tweeek this to get the type out
private string GetTemplate(string templateName, templatePath)
{
if(!_templateContainer.Conatains(templateName))
{
var text = File.ReadAllText(templatePath);
_templateContainer[templateName] = text;
}
return _templateContainer[templateName];
}
private FileInfo Export(List<Model> modelList)
{
string timeStr = Datetime.Now;
string archiveFileName = "Main.zip";
string archivePath = Path.Combine(_reportFolderPath, archiveFileName);
using (ZipArchive archive = ZipFile.Open(archivePath, ZipArchiveMode.Create))
{
foreach (var item in modelList)
{
var templateFilePath = Path.Combine(_reportTemplateFolder, TemplateName); //<--TemplateName seems like a local private
//these should come from where cant see where...
var template = GetTemplate( TemplateName, templateFilePath)
string modelResponse = ProcessModel(item,template,TemplateKey ); //<-- why is not passing in the template
//step 2;
//making this above done in parrell and then add aync, but before all that measure what is taking time
string pathname = MakeFileName(_reportFolderPath, reportFilelName, timeStr);
SaveToDisk(pathname, modelResponse);
string fileName = model.name + model.Id;
archive.CreateEntryFromFile(filePath, fileName + ".xml");
}
archive.Dispose();
}
return new FileInfo(archivePath);
}
private string MakeFileName(string path ,string filename, string tStamp)
{
string reportFilelName = fileName + "_" + timeStr + ".xml";
string filePath = Path.Combine(_reportFolderPath, reportFilelName);
return filePath;
}
private void SaveToDisk(string filePath, string content)
{
using (var file = new StreamWriter(filePath))
{
file.Write(processedTemplate);
}
}
public static string ProcessTemplate(object model, string template, templateKey)
{
var result = templateService.RunCompile(template, templateKey, null, model);
return result;
}
}
When I am saving an image, it is getting saved by the Barcode name.
But If I modify the barcode name, then the image is gone, not saving.
I have noticed while debugging that the if(System.IO.File.Exists(imageFilePath)) is not executing when I am updating the barcode. But at the time of saving a new one, its executing.
How to correct this?
Updating code
public object Update(ItemEntity item)
{
var val = _itemRepository.Save(item);
if (item.ImageFileName != string.Empty || item.ImageOriginalFileName != string.Empty)
{
string result = JsonConvert.SerializeObject(val);
var definition = new { Success = false, EntryMode = string.Empty, BarCode = string.Empty, ItemCode = string.Empty };
var info = JsonConvert.DeserializeAnonymousType(result, definition);
if (info.Success)
{
if (!string.IsNullOrEmpty(item.ImageOriginalFileName))
this.SaveImage(item.ImageFileName, (item.ImageOriginalFileName == "BARCODE" ? info.ItemCode : item.ImageOriginalFileName == "BARCODEYes" ? item.Barcode : item.ImageOriginalFileName));
}
}
if (item.DeleteImageFileName != string.Empty && item.ImageFileName == string.Empty) // Image file removed but no new image file is uploaded[Bug Id :34754 -No image is uploaded, when a user re-uploads an image after deleting a previous one.]
{
this.DeleteImage(item.DeleteImageFileName);
}
return val;
}
Saving Code
public void SaveImage(string fileName, string originalFileName)
{
string tempFileName = fileName;
if (!string.IsNullOrEmpty(tempFileName))
{
// move file from temp location to actual loation
var webAppPath = System.Web.Hosting.HostingEnvironment.MapPath("~");
var splitPath = webAppPath.Split("\\".ToCharArray()).ToList();
var upLevel = splitPath.Count - 1; // one level up
splitPath = splitPath.Take(upLevel).ToList();
var UIFolder = "WebUI";
splitPath.AddRange(new string[] { UIFolder, "Temp", "ImageUpload", CurrentSession.UserId.Value.ToString(), "ItemImage" });
var webUIPath = splitPath.Aggregate((i, j) => i + "\\" + j);
var imageFilePath = Path.Combine(webUIPath.EnsureEndsWith('\\'), tempFileName);
if (System.IO.File.Exists(imageFilePath))
{
splitPath = webAppPath.Split("\\".ToCharArray()).ToList();
upLevel = splitPath.Count - 1; // one level up
splitPath = splitPath.Take(upLevel).ToList();
splitPath.AddRange(new string[] { "Shared", "ItemImage" });
webUIPath = splitPath.Aggregate((i, j) => i + "\\" + j);
// Check existence of folder, create if not found and Delete-Create if found
if (!Directory.Exists(webUIPath))
{
Logger.Debug("Create directory :" + webUIPath);
Directory.CreateDirectory(webUIPath);
}
originalFileName = originalFileName + ".jpg";
var imagDestPath = Path.Combine(webUIPath.EnsureEndsWith('\\'), originalFileName);
if (File.Exists(imagDestPath))
{
GC.Collect();
GC.WaitForPendingFinalizers();
Logger.Debug("Delete File :" + imagDestPath);
File.Delete(imagDestPath);
}
byte[] bytes = System.IO.File.ReadAllBytes(imageFilePath);
FileStream fs = new FileStream(imagDestPath, FileMode.Create, FileAccess.Write);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(bytes);
bw.Close();
}
}
}
HttpPostedFile file = context.Request.Files[j];
string fileName = file.FileName;
string fileExtension = System.IO.Path.GetExtension(filepath + file.FileName);
if (!string.IsNullOrEmpty(fileName)
{
string pathToSave_100 = HttpContext.Current.Server.MapPath(filepath) + fileName + fileExtension;
if (File.Exists(pathToSave_100))
{
File.Delete(pathToSave_100);
file.SaveAs(pathToSave_100);
}
else
{
file.SaveAs(pathToSave_100);
}
}
You can do like this:
string strFileExtension = Path.GetExtension(file.FileName);
i have try with postman in my local server to route the API
this is my code
[HttpPost]
[Route("photo")]
public IHttpActionResult Upload()
{
// LOCAL VARIABLE
int ErrCode = 1;
dynamic ExpObj = new ExpandoObject();
string FilePath = HttpContext.Current.Server.MapPath("/Img");
// GET SID & DECRYPTING OBJEK TO JSON OBJ
var HttpRequest = HttpContext.Current.Request;
string SID = GetSID(this.Request.Headers);
dynamic objek = GetobjekuMultipart(SID, HttpRequest.Form["objek"]);
// EXTRACT OBJEK
string UserID = objek.userID;
if (HttpRequest.Files.Count > 0)
{
// GET UPLOADED IMAGE
var PostedFile = HttpRequest.Files["image"];
// SET FILE NAME ( USERID + Right(FileName,10) )
string FileName = GetFileName(UserID, PostedFile.FileName, 10);
// SAVE IMAGE
string ImagePath = Path.Combine(FilePath, FileName);
PostedFile.SaveAs(ImagePath);
ExpObj.imageURL = ServerUrl + ServerPath + FileName;
}
else
{
ErrCode = -900;
}
// RETURN IF GOT ERROR
if (ErrCode < 0)
{
return StatusCode((HttpStatusCode)(ErrCode * (-1)));
}
// SERIALIZING & ENCRYPTING
string SerializedObj = JsonConvert.SerializeObject(ExpObj, JsonSetting);
string EncryptedReturn = Encrypt(SerializedObj, SID);
// RETURN
return Ok(EncryptedReturn);
}
and this is my public method (General Method)
public string Decrypt(string cipherText, string sid)
{
RNCryptor.Decryptor D = new Decryptor();
string DecryptedString = "";
if (Prod == true)
{
try
{
DecryptedString = D.Decrypt(cipherText, sid + SigningKey);
}
catch (Exception ex)
{
int ErrCode = -902; // Error in Decrypt
throw new HttpResponseException((HttpStatusCode)(ErrCode * (-1)));
}
}
else
{
DecryptedString = cipherText;
}
return DecryptedString.Trim();
}
public dynamic GetObjekMultipart(string sid, string Objek)
{
string StrObjek = Decrypt(Objek, sid);
return JsonConvert.DeserializeObject<dynamic>(StrObjek);
}
public string GetFileName(string UserID, string fileName, int length)
{
string FileName;
string FileFormat;
// GET FILE FORMAT
string[] Words = fileName.Split('.');
FileFormat = "." + Words[Words.Length - 1];
// GET FILE NAME WITHOUT THE FILE FORMAT
FileName = fileName.Substring(0, fileName.Length - FileFormat.Length);
// SET THE FILE NAME
FileName = UserID + "-" + GetRight(FileName, length) + FileFormat;
return FileName;
}
and POSTMAN Result is "Object reference not set to an instance of an object"
the result said that the httprequest.form is NULL
please help :(
Hello I have signature like this:
which is encoded to a DataUrl specifically this string:
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAADICAYAAADGFbfiAAAYlElEQVR4Xu2dC8w1R1nHQSCIgIKVGLmoiLciFwUs... (long string)"
What i want to do is Convert this DataUrl to an PNG Image, and save the image to the device, this is what i am doing so far:
if (newItem.FieldType == FormFieldType.Signature)
{
if (newItem.ItemValue != null)
{
//string completeImageName = Auth.host + "/" + li[i];
string path;
string filename;
string stringName = newItem.ItemValue;
var base64Data = Regex.Match(stringName, #"data:image/(?<type>.+?),(?<data>.+)").Groups["data"].Value;
var binData = Convert.FromBase64String(base64Data);
path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
filename = Path.Combine(path, base64Data);
if (!File.Exists(filename))
{
using (var stream = new MemoryStream(binData))
{
//Code crashing here--------------------------
File.WriteAllBytes(filename, binData);
}
}
newItem.ItemValue = filename;
}
}
App.Database.SaveReportItem(newItem);
But my code is making my application to crash specifically in this line:
File.WriteAllBytes(filename, binData);
The sample I am using as reference (Link) is using a PictureBox but with Xamarin there is no use of a pictureBox.
Any Ideas?
As #SLaks mentioned I didn't need a MemoryStream, the problem with my code was the path and the filename for further help this is the working code:
if (newItem.FieldType == FormFieldType.Signature)
{
if (newItem.ItemValue != null)
{
//string completeImageName = Auth.host + "/" + li[i];
string path;
string filename;
string stringName = newItem.ItemValue;
var base64Data = Regex.Match(stringName, #"data:image/(?<type>.+?),(?<data>.+)").Groups["data"].Value;
var binData = Convert.FromBase64String(base64Data);
path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
//filename = Path.Combine(path, base64Data.Replace(#"/", string.Empty));
long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
string fileName = "Sn" + milliseconds.ToString() + ".PNG";
filename = Path.Combine(path, fileName);
if (!File.Exists(filename))
{
//using (var stream = new MemoryStream(binData))
//{
File.WriteAllBytes(filename, binData);
//}
}
newItem.ItemValue = filename;
}
}
App.Database.SaveReportItem(newItem);
And the image showed:
I just cleaned Mario's code and fine tuned regex:
public string SaveDataUrlToFile(string dataUrl, string savePath)
{
var matchGroups = Regex.Match(dataUrl, #"^data:((?<type>[\w\/]+))?;base64,(?<data>.+)$").Groups;
var base64Data = matchGroups["data"].Value;
var binData = Convert.FromBase64String(base64Data);
System.IO.File.WriteAllBytes(savePath, binData);
return savePath;
}