MultipartFormDataStreamProvider Cleanup - asp.net

If files are posted to my webapp, then I read them via MultipartFormDataStreamProvider.FileData.
I Initialize the provider like this:
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
And the provider nicely stores them as "~App_Data/BodyPart_{someguid}"
But how do I clean up those files after I'm done with them?

I know this question is old, but the best way I found to delete the temporary file was after processing it.
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
foreach (var file in provider.Files)
{
// process file upload...
// delete temporary file
System.IO.File.Delete(file.LocalFileName);
}

You could delete all files that are older than a certain timespan. e.g.
private void CleanTempFiles(string dir, int ageInMinutes)
{
string[] files = Directory.GetFiles(dir);
foreach (string file in files)
{
var time = File.GetCreationTime(file);
if (time.AddMinutes(ageInMinutes) < DateTime.Now)
{
File.Delete(file);
}
}
}
Then call it with something like:
CleanTempFiles(root, 60); // Delete all files older than 1 hour

Related

create Directory and if exist then rename it

i am developing application in which i want that if user create folder and if it is already present then folder should automatically renamed by appending number to folder name
suppose server has folder with name Time now if user again creates folder than it new folder will be Time1 again user creates folder with same name(Time or Time1) than new Folder should be created with Time2 and so on... This is what i have done so far but recursion always return wrong value.
public string checkIfExist(String path, String ProgramName, int itteration,out string strFolderName)
{
String uploadPath = "";
strFolderName = "";
String Mappath =HttpContext.Current.Server.MapPath(path);
if (Directory.Exists(Mappath))
{
String Path = HttpContext.Current.Server.MapPath((path + "" + ProgramName.Replace(" ", "_")));
// uploadPath += ++itteration ;
if (Directory.Exists(Path))
{
ProgramName += ++itteration;
strFolderName = ProgramName;
uploadPath = checkIfExist(path, ProgramName, itteration,out strFolderName);
}
}
return ProgramName;
}
Perhaps you could adapt this, to your need. I wrote it on the fly based on a piece of code I remember in an old file manager I was using in some projects, so please test it. This doesn't include creation and so on, based on your example I'm sure you can add that yourself but if you need help just comment below.
The idea is to pass the original name of the directory you want, and then return an appropriate new name if it exists, such as Test(1), Test(2), Test(n). Then once you get the name you need, you can create it directly.
protected string GetUniqueDirectoryName(string dirName)
{
string newDirName = dirName;
for (int i = 1; Directory.Exists(Server.MapPath("PATH_HERE") + newDirName); i++)
{
newDirName = string.Format("{0}({1})", dirName, i);
}
return newDirName;
}
Note: You will need to include System.IO and probably use HttpContext.Current.Server.MapPath instead of Server.MapPath
I don't know if I really understand what you are trying to do, but I think using recursion here is a little overkill. Try something like this:
string dirName = "Time";
int counter = 0;
string dir = dirName;
while(Directory.Exists(dir))
{
dir = String.Format("{0}{1}", dirName, (++counter).ToString());
}
Directory.CreateDirectory(dir);

Sqlite support for openfl

I'm trying to drop in sqlite support for saving the score and some flags. I need to open the db if it exists, then init game values based on db. If the db does not exist, I need to create/init it. The code below compiles but crashes for unknown reason.
package mygame;
<snip imports>
import sys.db.Types;
class ScoreDB extends sys.db.Object {
public var id : SId;
public var dbscore1 : SInt;
public var dbsound : SInt;
public var dbscore2 : SInt;
}
class mygame extends Sprite {
<snip var defines>
public function new () {
// start sqlite code
sys.db.Manager.initialize();
// db does exist
// then read values
// currentScore = score1.dbscore1;
// doSound = score1.dbsound;
// doScore = score1.dbscore2;
// db does not exist:
var cnx = sys.db.Sqlite.open("mybase.db");
sys.db.Manager.cnx = cnx;
sys.db.TableCreate.create(ScoreDB.manager);
var score1 = new ScoreDB();
score1.id = 0;
score1.dbscore1 = 0;
score1.dbsound = 0;
score1.dbscore2 = 0;
score1.insert();
currentScore = 0;
doSound = 0;
doScore = 0;
cnx.close();
// end sqlite code
super ();
initialize ();
construct ();
newGame ();
}
I actually just solved the same issue.
The problem is that the app is essentially a .zip file and cannot be edited. You need to create (and later access) the DB in the app storage directory.
To access the directory use following code:
private static var localStoragePath:String = openfl.utils.SystemPath.applicationStorageDirectory;
There is a known bug that the IDE's don't show the SystemPath class, but don't mind it, it will compile without problem.
Later, with your common tools you can read and write the directory, create new folders etc.
Here's a quick test, to make sure it works and doesn't crash:
// creating a test folder
sys.FileSystem.createDirectory(openfl.utils.SystemPath.applicationStorageDirectory + "/testFolder");
var form:TextFormat = new TextFormat(null, 22, 0xFFFFFF);
// getting contents of the storage dir
var arr = sys.FileSystem.readDirectory(openfl.utils.SystemPath.applicationStorageDirectory);
var tf:TextField = new TextField();
tf.defaultTextFormat = form;
tf.width = Lib.current.stage.stageWidth;
tf.height = Lib.current.stage.stageHeight;
tf.multiline = true;
tf.wordWrap = true;
tf.text = arr.toString();
addChild(tf);
as you'll see, the newly created folder is there. You can delete the line that creates the folder and you'll see it's safe.
Oh, an don't forget to add Android permissions in the XML file:
<android permission="android.permission.WRITE_EXTERNAL_STORAGE"/>
As far as I know there is no sqlite definitions in openfl. And the ones you use are just normal cpp target definition. I suppose the problem is they don't work on android. Even more: I'm quite sure the api definitions are ok, but it tries to load dll with a wrong name, which probably kills your app without even letting out an error. Try to look into implementation(it is short and easy to understand) and change the dll name.

Web Api Help Page XML comments from more than 1 files

I have different plugins in my Web api project with their own XML docs, and have one centralized Help page, but the problem is that Web Api's default Help Page only supports single documentation file
new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/Documentation.xml"))
How is it possible to load config from different files? I wan to do sth like this:
new XmlDocumentationProvider("PluginsFolder/*.xml")
You can modify the installed XmlDocumentationProvider at Areas\HelpPage to do something like following:
Merge multiple Xml document files into a single one:
Example code(is missing some error checks and validation):
using System.Xml.Linq;
using System.Xml.XPath;
XDocument finalDoc = null;
foreach (string file in Directory.GetFiles(#"PluginsFolder", "*.xml"))
{
if(finalDoc == null)
{
finalDoc = XDocument.Load(File.OpenRead(file));
}
else
{
XDocument xdocAdditional = XDocument.Load(File.OpenRead(file));
finalDoc.Root.XPathSelectElement("/doc/members")
.Add(xdocAdditional.Root.XPathSelectElement("/doc/members").Elements());
}
}
// Supply the navigator that rest of the XmlDocumentationProvider code looks for
_documentNavigator = finalDoc.CreateNavigator();
Kirans solution works very well. I ended up using his approach but by creating a copy of XmlDocumentationProvider, called MultiXmlDocumentationProvider, with an altered constructor:
public MultiXmlDocumentationProvider(string xmlDocFilesPath)
{
XDocument finalDoc = null;
foreach (string file in Directory.GetFiles(xmlDocFilesPath, "*.xml"))
{
using (var fileStream = File.OpenRead(file))
{
if (finalDoc == null)
{
finalDoc = XDocument.Load(fileStream);
}
else
{
XDocument xdocAdditional = XDocument.Load(fileStream);
finalDoc.Root.XPathSelectElement("/doc/members")
.Add(xdocAdditional.Root.XPathSelectElement("/doc/members").Elements());
}
}
}
// Supply the navigator that rest of the XmlDocumentationProvider code looks for
_documentNavigator = finalDoc.CreateNavigator();
}
I register the new provider from HelpPageConfig.cs:
config.SetDocumentationProvider(new MultiXmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/")));
Creating a new class and leaving the original one unchanged may be more convenient when upgrading etc...
Rather than create a separate class along the lines of XmlMultiDocumentationProvider, I just added a constructor to the existing XmlDocumentationProvider. Instead of taking a folder name, this takes a list of strings so you can still specify exactly which files you want to include (if there are other xml files in the directory that the Documentation XML are in, it might get hairy). Here's my new constructor:
public XmlDocumentationProvider(IEnumerable<string> documentPaths)
{
if (documentPaths.IsNullOrEmpty())
{
throw new ArgumentNullException(nameof(documentPaths));
}
XDocument fullDocument = null;
foreach (var documentPath in documentPaths)
{
if (documentPath == null)
{
throw new ArgumentNullException(nameof(documentPath));
}
if (fullDocument == null)
{
using (var stream = File.OpenRead(documentPath))
{
fullDocument = XDocument.Load(stream);
}
}
else
{
using (var stream = File.OpenRead(documentPath))
{
var additionalDocument = XDocument.Load(stream);
fullDocument?.Root?.XPathSelectElement("/doc/members").Add(additionalDocument?.Root?.XPathSelectElement("/doc/members").Elements());
}
}
}
_documentNavigator = fullDocument?.CreateNavigator();
}
The HelpPageConfig.cs looks like this. (Yes, it can be fewer lines, but I don't have a line limit so I like splitting it up.)
var xmlPaths = new[]
{
HttpContext.Current.Server.MapPath("~/bin/Path.To.FirstNamespace.XML"),
HttpContext.Current.Server.MapPath("~/bin/Path.To.OtherNamespace.XML")
};
var documentationProvider = new XmlDocumentationProvider(xmlPaths);
config.SetDocumentationProvider(documentationProvider);
I agree with gurra777 that creating a new class is a safer upgrade path. I started with that solution but it involves a fair amount of copy/pasta, which could easily get out of date after a few package updates.
Instead, I am keeping a collection of XmlDocumentationProvider children. For each of the implementation methods, I'm calling into the children to grab the first non-empty result.
public class MultiXmlDocumentationProvider : IDocumentationProvider, IModelDocumentationProvider
{
private IList<XmlDocumentationProvider> _documentationProviders;
public MultiXmlDocumentationProvider(string xmlDocFilesPath)
{
_documentationProviders = new List<XmlDocumentationProvider>();
foreach (string file in Directory.GetFiles(xmlDocFilesPath, "*.xml"))
{
_documentationProviders.Add(new XmlDocumentationProvider(file));
}
}
public string GetDocumentation(System.Reflection.MemberInfo member)
{
return _documentationProviders
.Select(x => x.GetDocumentation(member))
.FirstOrDefault(x => !string.IsNullOrWhiteSpace(x));
}
//and so on...
The HelpPageConfig registration is the same as in gurra777's answer,
config.SetDocumentationProvider(new MultiXmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/")));

How do I do "git show sha1:file" using JGit

I clone a repository as bare on my local disk using JGit. Now, I need to read the contents of a file at any given commit id (SHA1). How do I do this ?
The comment of RĂ¼diger Herrmann in this answer contains the relevant hints; but to make it easier for the friends of copy & paste solutions here my complete self-contained example code of a junit test that creates a revision of a file and then retrieves the contents of this revision. Works with jGit 4.2.0.
#Test
public void test() throws IOException, GitAPIException
{
//
// init the git repository in a temporary directory
//
File repoDir = Files.createTempDirectory("jgit-test").toFile();
Git git = Git.init().setDirectory(repoDir).call();
//
// add file with simple text content
//
String testFileName = "testFile.txt";
File testFile = new File(repoDir, testFileName);
writeContent(testFile, "initial content");
git.add().addFilepattern(testFileName).call();
RevCommit firstCommit = git.commit().setMessage("initial commit").call();
//
// given the "firstCommit": use its "tree" and
// localize the test file by its name with the help of a tree parser
//
Repository repository = git.getRepository();
try (ObjectReader reader = repository.newObjectReader())
{
CanonicalTreeParser treeParser = new CanonicalTreeParser(null, reader, firstCommit.getTree());
boolean haveFile = treeParser.findFile(testFileName);
assertTrue("test file in commit", haveFile);
assertEquals(testFileName, treeParser.getEntryPathString());
ObjectId objectForInitialVersionOfFile = treeParser.getEntryObjectId();
// now we have the object id of the file in the commit:
// open and read it from the reader
ObjectLoader oLoader = reader.open(objectForInitialVersionOfFile);
ByteArrayOutputStream contentToBytes = new ByteArrayOutputStream();
oLoader.copyTo(contentToBytes);
assertEquals("initial content", new String(contentToBytes.toByteArray(), "utf-8"));
}
git.close();
}
// simple helper to keep the main code shorter
private void writeContent(File testFile, String content) throws IOException
{
try (OutputStreamWriter wr = new OutputStreamWriter(new FileOutputStream(testFile), Charset.forName("utf-8")))
{
wr.append(content);
}
}
Edit to add: another, probably better example is at https://github.com/centic9/jgit-cookbook/blob/master/src/main/java/org/dstadler/jgit/api/ReadFileFromCommit.java
By using this. Iterable<RevCommit> gitLog = gitRepo.log().call(); you can get all the commit hash from that object.

MethodAccessException when updating a record in sqlite db

I encounter this exception when I try to updating a record with following statement.
UPDATE GroupTable SET groupId=100 WHERE groupId=101
I tested the statement under SQLite Manager of Firefox plug-in, and it works.
The error message is as following image. It crashed at the os_win_c.cs, the method named getTempname().
Well, I modified the original codes and fixed this bug.
The Path.GetTempPath() doesn't work because the sandbox enviroment. It has no access right.
I fixed by following codes. And it works now.
static int getTempname(int nBuf, StringBuilder zBuf)
{
const string zChars = "abcdefghijklmnopqrstuvwxyz0123456789";
StringBuilder zRandom = new StringBuilder(20);
i64 iRandom = 0;
for (int i = 0; i < 20; i++)
{
sqlite3_randomness(1, ref iRandom);
zRandom.Append((char)zChars[(int)(iRandom % (zChars.Length - 1))]);
}
//! Modified by Toro, 2011,05,10
string tmpDir = "tmpDir";
IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();
store.CreateDirectory(tmpDir);
//zBuf.Append(Path.GetTempPath() + SQLITE_TEMP_FILE_PREFIX + zRandom.ToString());
zBuf.Append(tmpDir + "/" + SQLITE_TEMP_FILE_PREFIX + zRandom.ToString());
return SQLITE_OK;
}
The above patch will result in an extra folder tmpDir in the isolatedstorage, and the temp files won't be deleted automatically, so it needs to be delete by self. I tried to delete those files in tmpDir in the method of winClose inside os_win_c.cs, and I found it will result in crash when I do VACUUM. Finally, I delete those tmp files when I closed the database. The following is a Dispose method in SQLiteConnection class.
public void Dispose()
{
if (_open)
{
// Original codes for close sqlite database
Sqlite3.sqlite3_close(_db);
_db = null;
_open = false;
// Clear tmp files in tmpDir, added by Toro 2011,05,13
IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();
string tmpDir = "tmpDir";
if (store.DirectoryExists(tmpDir) == false) return;
string searchPath = System.IO.Path.Combine(tmpDir, "*.*");
foreach (string file in store.GetFileNames(searchPath)) {
store.DeleteFile(System.IO.Path.Combine(tmpDir, file));
}
}
}

Resources