Web API handle uploaded files for delete - c#

ok I have this code that handle a file been upload through a simple web form
CustomMultipartFormDataStreamProvider provider = new CustomMultipartFormDataStreamProvider(#"C:\inetpub\wwwroot\myapp\Images");
//var provider = new MultipartFormDataStreamProvider(#"C:\inetpub\wwwroot\myapp\Images");
var Image = "";
var Dir = "";
var CurrentPath = "";
string UploadType = "";
string ImageName = "";
// Read the form data.
await Request.Content.ReadAsMultipartAsync(provider);
// Show all the key-value pairs.
foreach (var key in provider.FormData.AllKeys)
{
foreach (var val in provider.FormData.GetValues(key))
{
if (key == "uploadType") UploadType = val;
if (key == "imageName") ImageName = val;
//Trace.WriteLine(string.Format("{0}: {1}", key, val));
}
}
foreach (MultipartFileData file in provider.FileData)
{
//Debug.WriteLine(file.Headers.ContentDisposition.FileName);
//Debug.WriteLine("Server file path: " + file.LocalFileName);
Image = Path.GetFileName(file.LocalFileName);
Dir = Path.GetDirectoryName(file.LocalFileName);
CurrentPath = file.LocalFileName;
}
if (UploadType == "update")
{
File.Delete(Dir + "\\" + Image);
File.Move(CurrentPath, Dir + "\\" + Image);
Imagen = ImageName;
}
return Request.CreateResponse(HttpStatusCode.OK, Image);
as some docs mention using await will cause the read process to be async, my problem is that I need to know when the file has been saved into the folder cause I want to delete it after if the UploadType form field is == to update, but it seems like when try this line
File.Delete(Dir + "\\" + Image);
the image is has not been saved yet and I got an error that the image don't exist, so my question is, how I can tell or be sure the image is ready in the dir? how can I tell the async process ends, thanks for any help on this!!

File.Exists is the method you should use.
Aside You should be using Path.Combine instead of building the path with concatenation.

Related

TextWriter not working because its being used by another process. Network 5.0

I am trying to create a console app on network version 5.0 using visual studio. The purpose is to read all the PNG files in a directory, and make a JSON file with the code:
{
"format_version": "1.16.100",
"minecraft:texture_set": {
"color": "*Filename*",
"metalness_emissive_roughness": "*Filename_mer*"
}
}
In it. And yes this is for Minecraft. The filename and the filename_mer are automatically filled in by code, but that isn't my issue.
static void Main(string[] args)
{
Console.WriteLine("Goto " + Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Packages\\Microsoft.MinecraftUWP_8wekyb3d8bbwe\\LocalState\\games\\com.mojang\\resource_packs" + " And find the resource pack you want to generate files into");
string pathname = Console.ReadLine();
#region Message
Console.WriteLine();
Console.WriteLine("Looking for folder...");
#endregion
string path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Packages\\Microsoft.MinecraftUWP_8wekyb3d8bbwe\\LocalState\\games\\com.mojang\\resource_packs\\" + pathname + "\\textures";
#region Message
Console.WriteLine();
Console.WriteLine("Folder found in");
Console.WriteLine(path);
#endregion
string[] directories = Directory.GetDirectories(path);
foreach (string paths in directories)
{
string[] files = Directory.GetFiles(paths);
foreach (string file in files)
{
string filenameWithType = file.Substring(file.LastIndexOf("\\") + 1);
string filename = filenameWithType.Substring(0, filenameWithType.LastIndexOf("."));
string thisPath = file.Substring(0, file.LastIndexOf("\\"));
if (filenameWithType.Substring(filenameWithType.LastIndexOf(".") + 1) == "png")
{
string newPath = thisPath + "\\" + filename + ".texture_set.json";
File.Create(newPath);
List<string> codeInFile = new List<string>();
codeInFile.Clear();
codeInFile.Add("{");
codeInFile.Add("\"format_version\": \"1.16.100\",");
codeInFile.Add("\"minecraft:texture_set\": {");
codeInFile.Add("\"color\": \"" + filename + "\",");
codeInFile.Add("\"metalness_emissive_roughness\": \"" + filename + "_mer\"");
codeInFile.Add("}");
codeInFile.Add("}");
TextWriter tw = new StreamWriter(newPath, false);
foreach (string line in codeInFile)
{
tw.WriteLine(line);
Console.WriteLine(line);
}
tw.Close();
string newPathtxt = thisPath + "\\" + filename + "_mer.png";
Bitmap bitmap = new Bitmap(file);
using (Bitmap b = new Bitmap(bitmap.Width, bitmap.Height))
{
using (Graphics g = Graphics.FromImage(b))
{
g.Clear(Color.Green);
}
b.Save(newPathtxt, ImageFormat.Png);
}
}
}
}
#region Message
Console.WriteLine("");
Console.WriteLine("All done, Your good to go!");
#endregion
Console.Read();
}
This is all my code, on the file. It reads a directory which you enter, looks through the textures file, and for each PNG file in there it creates a JSON file with the code specified earlier. Although when run the code gives me this error.
System.IO.IOException: 'The process cannot access the file 'C:\Users\https\AppData\Local\Packages\Microsoft.MinecraftUWP_8wekyb3d8bbwe\LocalState\games\com.mojang\resource_packs\Vanilla_Resource_Pack_1.17.10\textures\blocks\acacia_trapdoor.texture_set.json' because it is being used by another process.'
I cannot find any answers which fit my issue, I would appreciate any help.
This is a Minecraft Bedrock edition resource pack btw, not sure if that helps.
Don't do this File.Create(newPath); or rethink your problem. It looks like a typo.
In short File.Create(newPath) is creating a FileStream and discarding it, leaving the file open and with a share lock. If you are trying to pre-create the file, at least use the using statement:
using (File.Create(newPath));
or Close
File.Create(newPath).Close();
or
File.WriteAllText(newPath, String.Empty);
or
File.WriteAllBytes(newPath, Array.Empty<byte>());
If you are just trying to create or overwrite the file StreamWriter(newPath, false) is good enough.

how to store and retrieve multiple values inside single session variable

i am using dropzone to upload multiple files to the server. files will be uploaded to server while file names will be stored in table.
i am trying to add file names in session.
the problem here is that it doesn't add multiple file names inside single session
here is my code :
string imageSessList = context.Session["imageNames"].ToString(); //if i put this line at the begining, then the debugger doesn't even moves to foreach block
foreach (string s in context.Request.Files)
{
HttpPostedFile file = context.Request.Files[s];
string fileName = file.FileName;
string fileExtension = file.ContentType;
string strUploadFileExtension = fileName.Substring(fileName.LastIndexOf(".") + 1);
string strAllowedFileTypes = "***jpg***jpeg***png***gif***bmp***"; //allowed file types
string destFileName = "";
List<string> lstImageNames = new List<string>();
// else upload file
if (!string.IsNullOrEmpty(fileName))
{
if (strAllowedFileTypes.IndexOf("***" + strUploadFileExtension + "***") != -1) //check extension
{
if (context.Request.Files[0].ContentLength < 5 * 1024 * 1024) //check filesize
{
// generate file name
destFileName = Guid.NewGuid().ToString() + "." + strUploadFileExtension;
string destFilePath = HttpContext.Current.Server.MapPath("/resourceContent/") + destFileName;
//Save image names to session
lstImageNames.Add(destFileName);
context.Session["imageNames"] = lstImageNames;
file.SaveAs(destFilePath);
strMessage = "Success " + destFileName;
}
else
{
strMessage = "File Size can't be more than 5 MB.";
}
}
else
{
strMessage = "File type not supported!";
}
}
} // foreach
context.Response.Write(strMessage);
}
here i am able to add only single filename to session, not multiple.
how to store and maintain multiple file names in single session :
context.Session["imageNames"]
you need to get current list from session
List<string> lstImageNames= (List<string>)Session["imageNames"];
if(lstImageNames==null)
lstImageNames = new List<string>(); // create new list in the first time
now add new item to it.
lstImageNames.Add(destFileName);
set back to session
context.Session["imageNames"] = lstImageNames;

How to close a file handle byte[] firstHash = MD5.Create().ComputeHash(f1.OpenRead());

I have a piece of code which works nicely. However I need to close the file so I can perform file.move() function, this doesn't work because the file is used by another process. I need to use the correct file handle - can you guide me in the right direction?
static void DSCheckForDuplicates(string incomingfolder, string incomingarchivefolder, string quarantinefolder)
{
string[] F1 = Directory.GetFiles(incomingfolder);
string fname = "";
long FileOne;
long FileTwo;
bool FilesAreTrullyIdentical;
string FileStatusValue = "";
string Result = "";
string NewLocation = "";
foreach (string fileName in F1)
{
// FILE EXCLUSION LIST FROM DUPLICATE FILE CHECKS
if (fileName.Contains("xxx.DAT") || fileName.Contains("xxx.txt") || fileName.Contains("OrderHead.txt") )
{
Console.WriteLine("\nKnown file type..");
}
else
{
fname = Path.GetFileName(fileName);
FilesAreTrullyIdentical = false;
Console.WriteLine("Files present : The file is {0}...Press any key\n", fileName);
//Console.ReadKey();
if (File.Exists(incomingarchivefolder + #"\" + fname))
{
DuplicateFlag = true;
FileStatusValue = "DuplicateFilename";
DuplicateFileCounter++;
Narative += string.Format("\n________________________________________________________________________________________________________________\nFile Exception :{0}\n####################\n", DuplicateFileCounter );
Narative += string.Format ("Same filename exists in the two compared directories, Checking potential duplicate file contents in :{0}................\n", fileName);
FileInfo f1 = new FileInfo(fileName);
FileOne = f1.Length;
FileInfo f2 = new FileInfo(incomingarchivefolder + #"\" + fname);
FileTwo = f2.Length;
//if (FileOne == FileTwo)
//{
byte[] firstHash = MD5.Create().ComputeHash(f1.OpenRead());
byte[] secondHash = MD5.Create().ComputeHash(f2.OpenRead());
for (int i = 0; i < firstHash.Length; i++)
{
FilesAreTrullyIdentical = true;
if (firstHash[i] != secondHash[i])
FilesAreTrullyIdentical = false;
}
if (FilesAreTrullyIdentical == true)
{
FileStatusValue = "DuplicationFileNameDuplicateContents";
Console.WriteLine("Processed : WARNING!!! identical FILES contents FOUND {0}\n and {1}\n..............\n", fileName, incomingarchivefolder + #"\" + fname);
Narative += string.Format("\tProcessed : Please delete from incoming, WARNING!!! identical FILES contents\n\nPLEASE DELETE FILE:\t{0}..............\n", fileName);
Result = Path.GetFileName(fileName);
NewLocation += quarantinefolder + "\\" + Result;
Console.WriteLine("\n\n {0} ->\nMoving to {1} , press any key", fileName, NewLocation);
Console.ReadKey();
//File.Move(fileName, NewLocation); // THIS DOESNT WORK
You could capture the stream from f1.OpenRead() into a variable & pass that calling Close() when your done, instead however you should put the stream and MD5 reference within a using construct as currently you leave them undisposed. (This will also close the stream for you)
byte[] firstHash;
using (var stream = f1.OpenRead())
using (var md5 = MD5.Create())
{
firstHash = md5.ComputeHash(stream);
}

How to copy file from one library to another library using CSOM?

I need to copy a particular file from one library to another library.
At first, need to check if file is existing in that library.
If Existing, then need to overwrite file content and new sharepoint version should be updated for that document.
I need to do this using c# CSOM and sharepoint version is 2013.
Thanks in advance :)
public static void CopyDocuments(string srcUrl, string destUrl, string srcLibrary, string destLibrary, Login _login)
{
// set up the src client
SP.ClientContext srcContext = new SP.ClientContext(srcUrl);
srcContext.AuthenticationMode = SP.ClientAuthenticationMode.FormsAuthentication;
srcContext.FormsAuthenticationLoginInfo = new SP.FormsAuthenticationLoginInfo(_login.UserName, _login.Password);
// set up the destination context (in your case there is no needs to create a new context, because it would be the same library!!!!)
SP.ClientContext destContext = new SP.ClientContext(destUrl);
destContext.AuthenticationMode = SP.ClientAuthenticationMode.FormsAuthentication;
destContext.FormsAuthenticationLoginInfo = new SP.FormsAuthenticationLoginInfo(_login.UserName, _login.Password);
// get the list and items
SP.Web srcWeb = srcContext.Web;
SP.List srcList = srcWeb.Lists.GetByTitle(srcLibrary);
SP.ListItemCollection col = srcList.GetItems(new SP.CamlQuery());
srcContext.Load(col);
srcContext.ExecuteQuery();
// get the new list
SP.Web destWeb = destContext.Web;
destContext.Load(destWeb);
destContext.ExecuteQuery();
foreach (var doc in col)
{
try
{
if (doc.FileSystemObjectType == SP.FileSystemObjectType.File)
{
// get the file
SP.File f = doc.File;
srcContext.Load(f);
srcContext.ExecuteQuery();
// build new location url
string nLocation = destWeb.ServerRelativeUrl.TrimEnd('/') + "/" + destLibrary.Replace(" ", "") + "/" + f.Name;
// read the file, copy the content to new file at new location
SP.FileInformation fileInfo = SP.File.OpenBinaryDirect(srcContext, f.ServerRelativeUrl);
SP.File.SaveBinaryDirect(destContext, nLocation, fileInfo.Stream, true);
}
if (doc.FileSystemObjectType == SP.FileSystemObjectType.Folder)
{
// load the folder
srcContext.Load(doc);
srcContext.ExecuteQuery();
// get the folder data, get the file collection in the folder
SP.Folder folder = srcWeb.GetFolderByServerRelativeUrl(doc.FieldValues["FileRef"].ToString());
SP.FileCollection fileCol = folder.Files;
// load everyting so we can access it
srcContext.Load(folder);
srcContext.Load(fileCol);
srcContext.ExecuteQuery();
foreach (SP.File f in fileCol)
{
// load the file
srcContext.Load(f);
srcContext.ExecuteQuery();
string[] parts = null;
string id = null;
if (srcLibrary == "My Files")
{
// these are doc sets
parts = f.ServerRelativeUrl.Split('/');
id = parts[parts.Length - 2];
}
else
{
id = folder.Name;
}
// build new location url
string nLocation = destWeb.ServerRelativeUrl.TrimEnd('/') + "/" + destLibrary.Replace(" ", "") + "/" + id + "/" + f.Name;
// read the file, copy the content to new file at new location
SP.FileInformation fileInfo = SP.File.OpenBinaryDirect(srcContext, f.ServerRelativeUrl);
SP.File.SaveBinaryDirect(destContext, nLocation, fileInfo.Stream, true);
}
}
}
catch (Exception ex)
{
Log("File Error = " + ex.ToString());
}
}
}
Source: https://sharepoint.stackexchange.com/questions/114033/how-do-i-move-files-from-one-document-library-to-another-using-jsom
I strongly advise against using the approach suggested by Nikerym. You don't want to download the bytes only to upload them unmodified. It's slow and error-prone. Instead, use the built-in method provided by the CSOM API.
https://learn.microsoft.com/en-us/previous-versions/office/sharepoint-server/mt162553(v=office.15)?redirectedfrom=MSDN
var srcPath = "https://YOUR.sharepoint.com/sites/xxx/SitePages/Page.aspx";
var destPath = $"https://YOUR.sharepoint.com/sites/xxx/SitePages/CopiedPage.aspx";
MoveCopyUtil.CopyFileByPath(ctx, ResourcePath.FromDecodedUrl(srcPath), ResourcePath.FromDecodedUrl(destPath), false, new MoveCopyOptions());
ctx.ExecuteQuery();
You can configure the override behavior by adjusting the 4th and 5th arguments of the function signature.
[...]
bool overwrite,
MoveCopyOptions options
https://learn.microsoft.com/en-us/previous-versions/office/sharepoint-server/mt844930(v=office.15)

How I Can Show The Image?

I Make Upload Image In Asp.Net And I Really Save The Image In The Data Base But When i Want To Make A Query To Select The Image It Return The Source Of The Image With No Image Please I Want Any One Know The Solution Please Help Me.`enter code here This Is The Controller Code:
public ActionResult UpLoadImage(HttpPostedFileBase file)
{
if (file != null)
{
UpLoadDBEntities context = new UpLoadDBEntities();
file = Request.Files[0];
string filename = file.FileName;
string contenttype = file.ContentType;
string full = filename + " " + contenttype;
//string path = System.IO.Path.Combine(
// Server.MapPath("~/images/") + file.FileName);
file.SaveAs(HttpContext.Server.MapPath("~/Images/")
+ file.FileName);
Image_table it = new Image_table();
it.Image_Path = filename;
context.Image_table.Add(it);
context.SaveChanges();
}
return View();
}
public JsonResult ShowImage()
{
UpLoadDBEntities context = new UpLoadDBEntities();
Image_table it = new Image_table();
var showimage = (from itbl in context.Image_table
where itbl.ID == 8
select new { itbl.Image_Path });
return Json(showimage , JsonRequestBehavior.AllowGet);
}
You are setting the path as
it.Image_Path = filename;
Yet it gets store on the server as
file.SaveAs(HttpContext.Server.MapPath("~/Images/")
+ file.FileName);
I hope you can see it needs to be it.Image_Path = "~/Images/" + filename;. Also, make sure folks can actually access the path through IIS.

Categories