Attempting to open a user-specified file and process it, path is lost - asp.net

So, I'm working on my first ASP.NET MVC 3 application and one thing I need to do is handle some data that is exported from someone else's system and turn around and import it, on user action, into the system and perform some error checking, etc. on it.
Here's how I have attempted to solve this issue:
I've got a view with a div:
<div>
<span><b>Recipe Data:</b>
<input type="file" name="uploadFile" />
<input type="submit" value="Load" />
</span>
</div>
and that allows me to choose a file and then submit it. Then I've got a controller action that looks like this:
[HttpPost]
public ActionResult Index(HttpPostedFileBase uploadFile)
{
try
{
// attempt to read the file
}
catch (Exception)
{
throw;
}
}
So, when I'm using IE, I can examine the uploadFile parameter and it gives me a path like:
FileName:c:\\Users\\Matt\\Desktop\\TestFiles\\AppleBerry.xml
(which is exactly the full path to the file I picked)
But when I try the same thing in FireFox, that path is stripped off, so uploadFile.FileName is just AppleBerry.xml and the XDocument.Load tries to load it from:
C:\Program Files (x86)\Common files\Microsoft Shared\DevServer\10.0\AppleBerry.xml
So, I'm pretty sure that I'm going about this the wrong way and need some guidance. I need to read in that XML file, preferably via XDocument.Load() and then do some checks and eventually push the records in that xml file into a DB table. The only part I'm having issues with is this file path. Any help you can provide with this would be most appreciated.

Try loading the file directly from the request stream and don't rely on the FileName property because you haven't saved the file on the server yet so it won't find it:
[HttpPost]
public ActionResult Index(HttpPostedFileBase uploadFile)
{
if (uploadFile != null && uploadFile.ContentLength > 0)
{
try
{
// attempt to read the file
var doc = XDocument.Load(uploadFile.InputStream);
// TODO: do something with the XML document
}
catch (Exception)
{
// Make sure you do something more meaningful here
// instead of rethrowing and erasing the stacktrace
throw;
}
}
else
{
// The user didn't upload any file => take respective actions
}
}

The server does not have access to the client's file system so the original path is irrelevant. Furthermore the file is not saved onto the server file system, so you should be loading it from the InputStream property, as per Darin's answer.

Related

Meteor CollectionFS / GridFS verify correct upload of a file

In our Meteor App we sometimes run into the issue, after uploading a file that the generated download link is .../null and the file is not retrievable anymore or never was uploaded correctly.
There are no errors logged at all.
FileUploads.insert(file, function (err, fileObj) {
if (err) { // this error never triggers
log(err);
} else {
if(fileObj.isUploaded()) { // is true after correct or non correct upload
FileUploads.find(fileObj._id); // fetches correct metadata even if file upload was corrupt
if(fileObj.url()=== 'null') {
throw Meteor.Error(...) // never thrown even when URL was "null"
}
}
}
List of used cfs packages:
cfs:access-point#0.1.49_2
cfs:base-package#0.0.30
cfs:collection#0.5.5
cfs:collection-filters#0.2.4
cfs:data-man#0.0.6
cfs:file#0.1.17
cfs:gridfs#0.0.34
cfs:http-methods#0.0.32
cfs:http-publish#0.0.13
cfs:power-queue#0.9.11
cfs:reactive-list#0.0.9
cfs:reactive-property#0.0.4
cfs:standard-packages#0.5.10
cfs:storage-adapter#0.2.4
cfs:tempstore#0.1.6
cfs:upload-http#0.0.20
cfs:worker#0.1.5
So how can we make sure the file was uploaded correctly right after an upload?
fileObj,isUploaded() seems not reliable. Is there a better way to verify the correct upload?

Prevent access to file(s) to secure path based downloads

It is fairly common to allow users to download a file via having some path modifier in the URL
//MVC Action to download the correct file From our Content directory
public ActionResult GetFile(string name) {
string path = this.Server.MapPath("~/Content/" + name);
byte[] file = System.IO.File.ReadAllBytes(path);
return this.File(file, "html/text");
}
quoted from http://hugoware.net/blog/dude-for-real-encrypt-your-web-config
An application I'm working with has liberal path downloads ( directory based ) sprinkled throughout the application, hence it is super vulnerable to requests like "http://localhost:1100/Home/GetFile?name=../web.config" or ( ..%2fweb.config )
Is there an easy way to restrict access to the config file - do I need to provide a custom Server.MapPath with whitelisted directories - or is there a better way.
How do you secure your file downloads - are path based downloads inherently insecure?
A simple option, assuming that all files in the ~/Content directory are safe to download would be to verify that the path is actually under (or in) the ~/Content directory and not up from it, as ~/Content/../web.config would be. I might do something like this:
// MVC Action to download the correct file From our Content directory
public ActionResult GetFile(string name) {
// Safe path
var safePath = this.Server.MapPath("~/Content");
// Requested path
string path = this.Server.MapPath("~/Content/" + name);
// Make sure requested path is safe
if (!path.StartsWith(safePath))
// NOT SAFE! Do something here, like show an error message
// Read file and return it
byte[] file = System.IO.File.ReadAllBytes(path);
return this.File(file, "html/text");
}

Implement webdav for encrypted word document

I need to implement webdav in my application. So the user can edit word document, without need to download and back it upload to the server. However, the problem now, the document saved on webdav server are encrypted. Is it possible to use webdav for encrypted file?
Or another words, is it possible to make http-GET request to encrypted file
2080.enc (which actually encrypted word document)
[GET] /DAV/2016/02/2080.enc
and get a decrypted file word document as a response, so I can edit the word document? Many thanks
Regards
===============================================================
===============================================================
Here is actually the problem..
On the client side, I am going to download the document stored on webdav server like this
#item.GetDocumentActionTitle
<object id="winFirefoxPlugin" type="application/x-sharepoint" width="0" height="0" style="visibility: hidden;"></object>
<script>
function officelink(sDocumentUrl) {
$.get(sDocumentUrl, null, function (data) {
try {
new ActiveXObject("SharePoint.OpenDocuments.4").EditDocument(data);
return false;
}
catch (e) {
try {
document.getElementById("winFirefoxPlugin").EditDocument(data);
return false;
}
catch (e2) {
return true;
}
}
});
}
However, the url must be full path including domain name like this http://webdavserver.com/2016/02/2080.doc..
It work perfectly if it is a word document (2080.doc), however what actually stored in the server is NOT 2089.doc BUT 2080.sec (enrcypted word document)
If it is NOT word document, The function EditDocument wont be able to read the file. And later by saving the file, it must be encrypted as well
Can you understand my problem? What should I do?
Thanks

Meteor File Upload Not Working

I've added the packages cfs:standard-packages and cfs:filesystem to my meteor project.
I want to upload featured images for my blog using a form with this input.
<div class="form-group">
<label for="featuredImage">Featured Image</label>
<input type="file" id="fImage" required>
<p class="help-block">Please choose an image file.</p>
</div>
And the event javascript
Template.AddPost.events({
'change #fImage': function(event, template) {
var image = template.find('[id=fImage]').value;
var lastIndex = image.lastIndexOf("\\");
if (lastIndex >= 0) {
image = image.substring(lastIndex + 1);
}
if (!image.match(/\.(jpg|jpeg|png|gif)$/)) {
alert("not an image");
} else {
FS.Utility.eachFile(event, function(file) {
var fileObj = new FS.File(file);
Meteor.call('uploadFeaturedImage', fileObj);
});
}
}
});
The 'uploadFeaturedImage' method on the server is
Meteor.methods({
'uploadFeaturedImage': function(fileObj){
Uploads.insert(fileObj, function(err){
console.log(err);
});
}
});
When i choose an image file to upload i get this error -
"Exception while invoking method 'uploadFeaturedImage' Error: DataMan constructor received data that it doesn't support"
Anyone have any ideas why this is happening? Thank you.
I copied some explanation from the collectionFS documentation because it is really good described there.
When you need to insert a file that's located on a client, always call myFSCollection.insert on the client. While you could define your own method, pass it the fsFile, and call myFSCollection.insert on the server, the difficulty is with getting the data from the client to the server. When you pass the fsFile to your method, only the file info is sent and not the data. By contrast, when you do the insert directly on the client, it automatically chunks the file's data after insert, and then queues it to be sent chunk by chunk to the server. And then there is the matter of recombining all those chunks on the server and stuffing the data back into the fsFile. So doing client-side inserts actually saves you all of this complex work, and that's why we recommend it.
Have a look at HERE
So your method is not working because no data is sent to the server.

ASP.NET MVC 3, pass the file from server to client

Actually, this looks like the download feature, allowing a user to determine the local path where the file should be stored.
The whole thing is: the background program will generate a data file in the server, after that, I want to pass the data file from server to client.
I used FileStreamResult and FileContentResult, but it doesn't work.
A *.csv file was generated, then the file needs to transfer to the client. in controller , the code is very simple , like return new FilePathResult(filePath,"text/csv"); and I set the break point , the code execute without any exception , but I didn't see any web diaglog letting the user to select the path to save the csv file.
Try using return File()
public FileResult GetFile()
{
byte[] test = { 0 };
return File(test, "text/csv","TempFile.csv");
}
and calling it with an actionlink.
#Html.ActionLink("Download File","GetFile","Home")
Thank you guys, I changed the designe--place the csv file under the web root directory, (e.g. \File\Date\testing.csv) in the Controller method will return a json which point to the csv location (e.g. /File/Date/testing.csv) , the js should get the url and redirect to the /File/Date/testing.csv .
public FastJsonResult Download()
{
//generate the csv file under root path
//return the url point to the file
return JsonView(path);
}

Resources