I am tasked to create a web service API where for an example, when an URL http://localhost:12345/api/filereader/data.txt is entered in the web browser, the data which is in data.txt file has to be displayed in the web page. I am able to do it if I know the filepath of data.txt.
However another requirement is that I am not supposed to indicate the filepath (in my code) as the scenario is, user is supposed to be able to use the URL API and input the .txt file name as a parameter (from whichever computer/server they are using) to get the data of what is in the .txt file that they have indicated. Therefore there should not be any physical path in my code. Is it possible to achieve that?
Here is the code that I have tried (with filepath):
ReaderController.cs
[ResponseType(typeof(string))]
public IHttpActionResult Get(String FileName)
{
try
{
string fileName = FileName;
string path = "C:\\Users\\attsuap1\\Desktop\\" + fileName;
string result = File.ReadAllText(path);
var resultDTO = JsonConvert.DeserializeObject(result);
return Ok(resultDTO);
}
catch
{
var result = "File does not exist";
return Ok(new { ErrorMessage = result });
}
}
How do I edit this code to get what I want?
You are asking to load a file from a user device from your server. That is just not possible for security purposes (imagine what would happen if you could).
The only way to get access to a file from the user, is by letting the user send it using some sort of upload form or control. The posted data can be used by your server then.
Related
I am trying to get public shareable link of the uploaded files to GoogleDrive using GoogleDriveApi v3. I am able to upload the files and get FileId. I am not able to add Permission and shareable link to the uploaded files. I have searched numerous answers on the Internet and StackOverflow, but did not anything that would help me solve the problem. I have tried solutions that were provided for Java and Python, but I am getting error:
Google.GoogleApiException: 'The service drive has thrown an exception. HttpStatusCode is Forbidden. The resource body includes fields which are not directly writable.'
Here's my code:
public async Task UploadFileAsync(Stream file, string fileName, string fileMime, string folder, string fileDescription)
{
DriveService driveService = GetService();
var fileMetaData = new Google.Apis.Drive.v3.Data.File()
{
Name = filename, Description = fileDescription, MimeType = fileMime, Parents = new string[] { folder },
};
var request = driveService.Files.Create(fileMetaData, file, fileMime);
request.Fields = "id, webContentLink";
var response = await request.UploadAsync(cancellationToken);
if (response.Status != UploadStatus.Completed)
throw response. Exception;
var permission = new Permission { AllowFileDiscovery = true, Id = "id, webContentLink", Type = "anyone", Role = "reader" };
var createRequest = driveService.Permissions.Create(permission, request.ResponseBody.Id);
createRequest.Fields = "id, webContentLink";
await createRequest.ExecuteAsync();
Debug.WriteLine("Link: " + request.ResponseBody.WebContentLink);
}
I am getting the link in the statement request.ResponseBody.WebContentLink, but the permissions are not set on the file. Hence the file is not shared and the link does not work. Is there anything I am doing wrong?
Got it working after correcting the Permission initialization. Seems that Permission.Id is not writeable (hence the error The resource body includes fields which are not directly writable.). Thus, removed assignment of some value to Permission.Id.
Hence the correct way would be
var permission = new Permission { AllowFileDiscovery = true, Type = "anyone", Role = "reader" };
var fileId = request.ResponseBody.Id;
await driveService.Permissions.Create(permission, fileId).ExecuteAsync();
Hence, in this way we can set permissions on the uploaded file and make it shareable through code. Rest of the code is correct. Further we will get downloadable link using request.ResponseBody.WebContentLink.
The sharable link created through the google drive web application is not something that you can create or get via the google drive API.
The WebView link at the download links can only be used by someone who has permissions on the file
so you will need to add the user as reader for the file if you want them to be able to use that link
API flow to upload a file and grant access to a user.
Create a file via the file.create method uploading the file.
Then preform a permissions.create adding the user who you would like to be able to have access to download the file.
Then do a file.get to get the WebContentLink and the user should be able to access the file via their google drive account.
I have MVC web application where user draws a shape on a map and the coordinates of it should be saved in Json file in user's computer, particular location, so that it can be accessed and displayed for the user later. I get the coordinates. But how can I write the coordinates to Json file from a Javascript function?
Here's a way to write to a text file using FileSystemObject Reference (Windows Scripting) and JavaScript. See CreateTextFile Method for more info.
function WriteToTextFile(text, path, overwrite) {
var ov = false;
var fso = new ActiveXObject("Scripting.FileSystemObject");
if(overwrite === true)
ov = true;
var a = fso.CreateTextFile(path, overwrite);
a.WriteLine(text);
a.Close();
}
Usage:
var obj =
{
propA: "A",
propB: "B",
propC: 123
};
var text = JSON.stringify(obj);
var path = "c:\\testfile.txt";
WriteToTextFile(text, path, false);
Note that you need to install the ActiveX plugin and this only works on IE. What you want to achieve is not considered a good practice and poses security risks which is why the ideal way is to generate the file on the server and prompt the user to save it. I also don't see why you are using web with a local database. Basing on your requirement, I'd suggest using localStorage.
I am currently working on a 'download file' implementation using Web API 2.
However, as the files that can be downloaded are NOT stored in the database, I am passing in the full file path as the parameter for identification.
It seems the problem with this approach is that the filePath contains characters that are invalid for a URI... Has anyone got any suggestions to resolve this or an alternate approach?
Download file method:
[HttpGet]
[Route("Files/{*filePath}")]
public HttpResponseMessage Get([FromUri]string filePath)
{
try
{
var file = new FileInfo(filePath);
byte[] bytes = System.IO.File.ReadAllBytes(filePath);
var result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new ByteArrayContent(bytes);
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = file.Name + file.Extension;
return result;
}
catch(Exception ex)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
}
}
Requiring the client to put the full path in the URI (even if it were encoded so that it only contains valid characters for the URI) implies that you may be publishing these paths somewhere... this is not a great idea for a few reasons:
Security - full Path Disclosure and associated Relative Path Traversal
i.e. what's to stop someone passing in the path to a sensitive file (e.g. your web.config file) and potentially obtaining information that could assist with attacking your system?
Maintainability
Clients may maintain a copy of a URI for reuse or distribution - what happens if the file paths change? Some related conversation on this topic here: Cool URIs don't change
My suggestion - you don't have to put the files themselves in a database, but put a list of files in a database, and use a unique identifier in the URL (e.g. perhaps a slug or GUID). Look up the identifier in the database to discover the path, then return that file.
This ensures:
Nobody can read a file that you haven't indexed and determined is safe to be downloaded
If you move the files you can update the database and client URIs will not change
And to respond to your original question, you can easily ensure the unique identifier is only made up of URI safe characters
Once you have the database, over time you may also fine it useful to maintain other metadata in the database such as who uploaded the file, when, who downloaded it, and when, etc.
I am working on Document Management System in ASP.NET using C#. I store all folders and files on a windows server and save folder and file info in SQL database as well. Everytime, I create a folder or file on server, I append the name with unique id from database. Example: contact~432cace7-a39c-4db5-a38f-9efe5d289bbf.pdf
Now we have different users who have access to same folders and need a way to delete and download based on their access.
Example: I have 2 users, user-1 and user-2. I have a folder-1 which contains 2 files. file-1 is uploaded by user-1 and file-2 by user-2. Now when user-1 views the file in browser page, I show folder-1 and within that file-1 based on database query. But if user one selects folder-1 for download, it will go to the windows server and download both file-1 and file-2 as physically they are within same folder on server. Same is the case with delete too.
How can I handle this scenario?
Basically, handling in SQL is much easy with relational database but I am thinking how can this be done on windows server efficiently?
My Idea: Call a DB stored proc that returns list of ids and based on that generate the download zip or delete. But since there can be nesting of folder and files, how efficient will this be in performance?
Follow the code below and process :
In Js File :
var file_name = response.value[0]["name"];
var downloadurl = response.value[0]"#microsoft.graph.downloadUrl"];
//-----------------------------------------------------------------------//
function HandleIT(downloadurl,file_name) {
PageMethods.ProcessIT(downloadurl,file_name, onSucess, onError);
function onSucess(result) {
alert(result);
}
function onError(result) {
alert('Something wrong.');
}
}
In Code Behind us the Webmethod :
[WebMethod]
public static string ProcessIT(string downloadURL, string file_name)
{
// Create a new WebClient instance.
WebClient myWebClient = new WebClient();
string path = #"c:\";
string path_n_name = path + file_name;
// Download the Web resource and save it into the current filesystem folder.
myWebClient.DownloadFile(downloadURL, path_n_name);
return "SUCCESS";
}
This is how I delete files
if(fileName != null || fileName != string.empty)
{
if((System.IO.File.Exists(fileName))
System.IO.File.Delete(fileName);
}
Hope it works for you...!
I am using HTML input file to select the file. I have tried in JQUERY but I it returns fake path.
$("#inputfile").val()
I want to get selected file actual path e.g
D:\Documents\image.png
So I have tried to upload the file in ASP.NET MVC and check the path but It also gives file name.
[HttpPost]
public ActionResult GetFileName() {
var result = "";
if (Request.Files.Count > 0)
{
result = Request.Files[0].FileName;
}
return Json(result);
}
Is there any solution to get the path. I know this a browser security feature but I have to entertain the client requirement. Please suggest the solution if exist.
Thank you
Short answer - no way.
You cannot get the client's file path, only the filename.