I have this code, it checks if a photo exists and if it has been created within the past 14 days. The issue I am finding is that the code is passing the System.IO.File.Exists() but then when I go to return the file at the end, it errors with a "Could not find file". Anyone have any ideas? I am suspecting it is the way I am using Path.Combine?
EDIT
Managed to get it working by returning a filestream rather than a path.
var img = System.IO.File.OpenRead(PhotoPathAndFileName);
return File(img, "image/jpeg");
**
public IActionResult GetPhoto(string ID, int MaxHeight, int MaxWidth, bool isStudentImage = true)
{
var PhotoFileName = ID + "_" + MaxHeight.ToString() + "x" + MaxWidth.ToString() + ".jpg";
var PhotoPathAndFileName = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot\\images\\App_Data\\_cacheIDPhoto", PhotoFileName);
var FileExists = false;
if (System.IO.File.Exists(PhotoPathAndFileName))
{
var CreateDate = System.IO.File.GetCreationTime(PhotoPathAndFileName);
if (CreateDate < DateTime.Now.AddDays(-14))
{
System.IO.File.Delete(PhotoPathAndFileName);
}
else
{
FileExists = true;
}
}
if (!FileExists)
{
PhotoPathAndFileName = CreatePhotoFile(Convert.ToInt32(ID), PhotoPathAndFileName, MaxWidth, MaxHeight, isStudentImage);
}
return File(PhotoPathAndFileName, "image/jpeg");
}
Managed to get it working by returning a filestream rather than a path.
var img = System.IO.File.OpenRead(PhotoPathAndFileName);
return File(img, "image/jpeg");
Related
I have an existing program that does some processing a .pdf file and splitting it into multiple .pdf files based on looking for barcodes on the pages.
The program uses ImageMagick and C#.
I want to change it from outputting pdfs to outputting tifs. Look for the comment in the code below for where I would guess the change would be made.
I included the ImageMagick tag because someone might offer a commandline option that someone else can help me convert to C#.
private void BurstPdf(string bigPdfName, string targetfolder)
{
bool outputPdf = true; // change to false to output tif.
string outputExtension = "";
var settings = new MagickReadSettings { Density = new Density(200) };
string barcodePng = Path.Combine("C:\TEMP", "tmp.png");
using (MagickImageCollection pdfPageCollection = new MagickImageCollection())
{
pdfPageCollection.Read(bigPdfName, settings);
int inputPageCount = 0;
int outputPageCount = 0;
int outputFileCount = 0;
MagickImageCollection resultCollection = new MagickImageCollection();
string barcode = "";
string resultName = "";
IBarcodeReader reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>();
reader.Options.PossibleFormats.Add(BarcodeFormat.CODE_39);
reader.Options.TryHarder = false;
foreach (MagickImage pdfPage in pdfPageCollection)
{
MagickGeometry barcodeArea = getBarCodeArea(pdfPage);
IMagickImage barcodeImg = pdfPage.Clone();
barcodeImg.ColorType = ColorType.Bilevel;
barcodeImg.Depth = 1;
barcodeImg.Alpha(AlphaOption.Off);
barcodeImg.Crop(barcodeArea);
barcodeImg.Write(barcodePng);
inputPageCount++;
using (var barcodeBitmap = new Bitmap(barcodePng))
{
var result = reader.Decode(barcodeBitmap);
if (result != null)
{
// found a first page because it has bar code.
if (result.BarcodeFormat.ToString() == "CODE_39")
{
if (outputFileCount != 0)
{
// write out previous pages.
if (outputPdf) {
outputExtension = ".pdf";
} else {
// What do I put here to output a g4 compressed tif?
outputExtension = ".tif";
}
resultName = string.Format("{0:D4}", outputFileCount) + "-" + outputPageCount.ToString() + "-" + barcode + outputExtension;
resultCollection.Write(Path.Combine(targetfolder, resultName));
resultCollection = new MagickImageCollection();
}
barcode = standardizePhysicalBarCode(result.Text);
outputFileCount++;
resultCollection.Add(pdfPage);
outputPageCount = 1;
}
else
{
Console.WriteLine("WARNING barcode is not of type CODE_39 so something is wrong. check page " + inputPageCount + " of " + bigPdfName);
if (inputPageCount == 1)
{
throw new Exception("barcode not found on page 1. see " + barcodePng);
}
resultCollection.Add(pdfPage);
outputPageCount++;
}
}
else
{
if (inputPageCount == 1)
{
throw new Exception("barcode not found on page 1. see " + barcodePng);
}
resultCollection.Add(pdfPage);
outputPageCount++;
}
}
if (File.Exists(barcodePng))
{
File.Delete(barcodePng);
}
}
if (resultCollection.Count > 0)
{
if (outputPdf) {
outputExtension = ".pdf";
} else {
// What do I put here to output a g4 compressed tif?
outputExtension = ".tif";
}
resultName = string.Format("{0:D4}", outputFileCount) + "-" + outputPageCount.ToString() + "-" + barcode + outputExtension;
resultCollection.Write(Path.Combine(targetfolder, resultName));
outputFileCount++;
}
}
}
[EDIT] The above code is what I am using (which some untested modifications) to split a .pdf into other .pdfs. I want to know how to modify this code to output tiffs. I put a comment in the code where I think the change would go.
[EDIT] So encouraged by #fmw42 I just ran the code with the .tif extension enabled. Looks like it did convert to a .tif, but the tif is not compressed. I am surprised that IM just configures the output based on the extension name of the file. Handy I guess, but just seems a little loose.
[EDIT] I figured it out. Although counter-intuitive ones sets the compression on the read of the file. I am reading a .pdf but I set the compression to Group for like this:
var settings = new MagickReadSettings { Density = new Density(200), Compression = CompressionMethod.Group4 };
The thing I learned was that simply naming the output file .tif tells IM to output a tif. That is a handy way to do it, but it just seems sloppy.
I have the following code which works fine for Move, but doesn't work for copy
// relativeSourceFolderUrl = "/SubSeries/DEV010/files/dev010-007-2018/parent/copyThisFolder"
// relativeDestinationFolderUrl= "/SubSeries/DEV010/files/dev010-007-2018/parent/child"
// fileName = "copyThisFoler"
// moveItem = false
public Folder MoveOrCopyFolder(String relativeSourceFolderUrl, String relativeDestinationFolderUrl, String fileName, bool moveItem)
{
Folder folder = ClientContext.Web.GetFolderByServerRelativeUrl(relativeDestinationFolderUrl);
// Check if file or folder exists and alter name
fileName = CheckFileOrFolderExistsInFolder(fileName, folder, false);
// In this case the function returns a fileName of "copyThisFolder"
var file = ClientContext.Web.GetFileByServerRelativeUrl(relativeSourceFolderUrl);
ClientContext.Load(file.ListItemAllFields);
ClientContext.ExecuteQuery();
if (moveItem)
file.MoveTo(relativeDestinationFolderUrl + "/" + fileName, MoveOperations.None);
else
file.CopyTo(relativeDestinationFolderUrl + "/" + fileName, false);
ClientContext.ExecuteQuery();
return null;
}
It breaks on this line
file.CopyTo(relativeDestinationFolderUrl + "/" + fileName, false);
The error is
Additional information: The URL '/SubSeries/DEV010/files/dev010-007-2018/parent/copythisfolder' is invalid. It may refer to a nonexistent file or folder, or refer to a valid file or folder that is not in the current Web.
The Move works, but its odd that similar code doesn't work for copy.
In the end I used this post:
https://sharepoint.stackexchange.com/questions/97471/copy-all-items-in-a-folder-to-another-location/250233?noredirect=1#comment266907_250233
Which lead me to this solution:
public void CopyFiles(string listTitle, string srcRelativeSource, string destRelativeSource)
{
var srcList = ClientContext.Web.Lists.GetByTitle(listTitle);
var qry = CamlQuery.CreateAllItemsQuery();
qry.FolderServerRelativeUrl = string.Format("/{0}", srcRelativeSource);
var srcItems = srcList.GetItems(qry);
ClientContext.Load(srcItems, icol => icol.Include(i => i.FileSystemObjectType, i => i["FileRef"], i => i.File));
ClientContext.ExecuteQuery();
createThisFolder(destRelativeSource);
foreach (var item in srcItems)
{
switch (item.FileSystemObjectType)
{
case FileSystemObjectType.Folder:
var destFolderUrl = ((string)item["FileRef"]).ToLower().Replace(srcRelativeSource, destRelativeSource);
createThisFolder(destFolderUrl);
break;
case FileSystemObjectType.File:
var destFileUrl = item.File.ServerRelativeUrl.ToLower().Replace(srcRelativeSource, destRelativeSource);
item.File.CopyTo(destFileUrl, true);
ClientContext.ExecuteQuery();
break;
}
}
}
private void createThisFolder(string destFolderUrl)
{
//change destFolderUrl into absolute url
Uri u = new Uri(ClientContext.Web.Context.Url);
//remove the string after the last slash
int idx = destFolderUrl.LastIndexOf('/');
string path = destFolderUrl.Substring(0, idx);
string lastFolder = destFolderUrl.Split('/').Last();
string filtered = (path.StartsWith("/")) ? path.Substring(1) : path;
string url = u.GetLeftPart(UriPartial.Authority) + "/" + filtered;
CreateFolder(url, lastFolder);
}
I have an issue with Files.
I am doing an image importer so clients put their files on an FTP server and then they can import it in the application.
During the import process I copy the file in the FTP Folder to another folder with File.copy
public List<Visuel> ImportVisuel(int galerieId, string[] images)
{
Galerie targetGalerie = MemoryCache.GetGaleriById(galerieId);
List<FormatImage> listeFormats = MemoryCache.FormatImageToList();
int i = 0;
List<Visuel> visuelAddList = new List<Visuel>();
List<Visuel> visuelUpdateList = new List<Visuel>();
List<Visuel> returnList = new List<Visuel>();
foreach (string item in images)
{
i++;
Progress.ImportProgress[Progress.Guid] = "Image " + i + " sur " + images.Count() + " importées";
string extension = Path.GetExtension(item);
string fileName = Path.GetFileName(item);
string originalPath = HttpContext.Current.Request.PhysicalApplicationPath + "Uploads\\";
string destinationPath = HttpContext.Current.Server.MapPath("~/Images/Catalogue") + "\\";
Visuel importImage = MemoryCache.GetVisuelByFilName(fileName);
bool update = true;
if (importImage == null) { importImage = new Visuel(); update = false; }
Size imageSize = importImage.GetJpegImageSize(originalPath + fileName);
FormatImage format = listeFormats.Where(f => f.width == imageSize.Width && f.height == imageSize.Height).FirstOrDefault();
string saveFileName = Guid.NewGuid() + extension;
File.Copy(originalPath + fileName, destinationPath + saveFileName);
if (format != null)
{
importImage.format = format;
switch (format.key)
{
case "Catalogue":
importImage.fileName = saveFileName;
importImage.originalFileName = fileName;
importImage.dossier = targetGalerie;
importImage.dossier_id = targetGalerie.id;
importImage.filePath = "Images/Catalogue/";
importImage.largeur = imageSize.Width;
importImage.hauteur = imageSize.Height;
importImage.isRoot = true;
if (update == false) { MemoryCache.Add(ref importImage); returnList.Add(importImage); }
if (update == true) visuelUpdateList.Add(importImage);
foreach (FormatImage f in listeFormats)
{
if (f.key.StartsWith("Catalogue_"))
{
string[] keys = f.key.Split('_');
string destinationFileName = saveFileName.Insert(saveFileName.IndexOf('.'), "-" + keys[1].ToString());
string destinationFileNameDeclinaison = destinationPath + destinationFileName;
VisuelResizer declinaison = new VisuelResizer();
declinaison.Save(originalPath + fileName, f.width, f.height, 1000, destinationFileNameDeclinaison);
Visuel visuel = MemoryCache.GetVisuelByFilName(fileName.Insert(fileName.IndexOf('.'), "-" + keys[1].ToString()));
update = true;
if (visuel == null) { visuel = new Visuel(); update = false; }
visuel.parent = importImage;
visuel.filePath = "Images/Catalogue/";
visuel.fileName = destinationFileName;
visuel.originalFileName = string.Empty;
visuel.format = f;
//visuel.dossier = targetGalerie; On s'en fout pour les déclinaisons
visuel.largeur = f.width;
visuel.hauteur = f.height;
if (update == false)
{
visuelAddList.Add(visuel);
}
else
{
visuelUpdateList.Add(visuel);
}
//importImage.declinaisons.Add(visuel);
}
}
break;
}
}
}
MemoryCache.Add(ref visuelAddList);
// FONCTION à implémenter
MemoryCache.Update(ref visuelUpdateList);
return returnList;
}
After some processes on the copy (the original file is no more used)
the client have a pop-up asking him if he wants to delete the original files in the ftp folder.
If he clicks on Ok another method is called on the same controller
and this method use
public void DeleteImageFile(string[] files)
{
for (int i = 0; i < files.Length; i++)
{
File.Delete(HttpContext.Current.Request.PhysicalApplicationPath + files[i].Replace(#"/", #"\"));
}
}
This method works fine and really delete the good files when I use it in other context.
But here I have an error message:
Process can't acces to file ... because it's used by another process.
Someone have an idea?
Thank you.
Here's the screenshot of Process Explorer
There are couple of thing you can do here.
1) If you can repro it, you can use Process Explorer at that moment and see which process is locking the file and if the process is ur process then making sure that you close the file handle after your work is done.
2) Use try/catch around the delete statement and retry after few seconds to see if the file handle was released.
3) If you can do it offline you can put in some queue and do the deletion on it later on.
You solve this by using c# locks. Just embed your code inside a lock statement and your threads will be safe and wait each other to complete processing.
I found the solution:
in my import method, there a call to that method
public void Save(string originalFile, int maxWidth, int maxHeight, int quality, string filePath)
{
Bitmap image = new Bitmap(originalFile);
Save(ref image, maxWidth, maxHeight, quality, filePath);
}
The bitmap maintains the file opened blocking delete.
just added
image.Dispose();
in the methos and it work fine.
Thank you for your help, and thank you for process explorer. Very useful tool
I have a problem with this method, i want to return a PDF file and when the method it's over i want to delete de file from the directory.
public ActionResult DescargaPdfCompara(string id)
{
var rutaPdf = string.Empty;
var type = "application/pdf";
try
{
DateTime ahora = DateTime.Now;
var numeroAleatorio = new Random();
int numeroRandomico = numeroAleatorio.Next(100000000, 1000000000);
string Ruta = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"Reportes\" + Convert.ToString(ahora.Year + ahora.Month + ahora.Day + ahora.Hour + ahora.Minute + ahora.Second + numeroRandomico) + ".pdf");
var result = SimuModel.ObtenerSabanaReporteComparativo(id);
var resumen = SimuModel.ObtenerPreExcel(result);
SimuModel.GenerarPdfCompa(result, resumen, Ruta);
rutaPdf = Ruta;
return File(rutaPdf, type);
}
catch (Exception e)
{
throw e;
}
finally
{
System.IO.File.Delete(rutaPdf);
}
}
In the finally i delete the file but i got an error because the method can't find the file, for some reason the method delete the file before return it.
PD: Sorry for my english, i'm from Chile.
Thanks fro your answers!
You can use System.IO.File.ReadAllBytes to read all the file contents to memory, then delete the file and return the contents with another overload of Controller.File method:
public ActionResult GetFile()
{
var fileName = Path.GetTempFileName();
System.IO.File.WriteAllText(fileName, "Hola, Chile!");
var bytes = System.IO.File.ReadAllBytes(fileName);
System.IO.File.Delete(fileName);
return File(bytes, "text/plain", "file.txt");
}
Change return type ContentResult
remove finally section.
public ContentResult DescargaPdfCompara(string id)
{
var rutaPdf = string.Empty;
var type = "application/pdf";
try
{
DateTime ahora = DateTime.Now;
var numeroAleatorio = new Random();
int numeroRandomico = numeroAleatorio.Next(100000000, 1000000000);
string Ruta = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"Reportes\" + Convert.ToString(ahora.Year + ahora.Month + ahora.Day + ahora.Hour + ahora.Minute + ahora.Second + numeroRandomico) + ".pdf");
var result = SimuModel.ObtenerSabanaReporteComparativo(id);
var resumen = SimuModel.ObtenerPreExcel(result);
SimuModel.GenerarPdfCompa(result, resumen, Ruta);
rutaPdf = Ruta;
return Content(rutaPdf, type);
}
catch (Exception e)
{
throw e;
}
}
public ActionResult GeneratePdf(int id)
{
var labelRepository = new LabelRepository();
var label = labelRepository.GetLabel(id);
if (String.IsNullOrEmpty(label.PDFLocation))
{
var action = Url.Content("~/Label/ViewPdf/" + id); //doc
Doc theDoc = new Doc();
string filename = Guid.NewGuid().ToString();
string path = Server.MapPath("~/" + filename + ".pdf");
theDoc.AddImageUrl("action");
theDoc.Save(path);
theDoc.Clear();
label.PDFLocation = path;
labelRepository.Save();
return base.File(path, "application/pdf");
}
else
{
return base.File(label.PDFLocation, "application/pdf");
}
}
This won't add my image url so my pdf won't open up so I can see it. Any ideas?-
In the example here, a complete URL is being passed to the AddImageUrl() function, not a fragment of an URL, as your example shows.
Perhaps you need a call to RouteUrl() so that you can get a complete Url to pass to your AddImageUrl() method?