How to serve woff2 files from owin FileServer - mime-types

Since font awesome 4.3, they added the fonts as woff2 format.
I'm guetting 404ed when trying to serve this file through owin :
app.UseFileServer(new FileServerOptions() {
RequestPath = PathString.Empty,
FileSystem = new PhysicalFileSystem(#"banana")
});
How do I serve woff2 mime type files through file server in owin ?

Two possibilities :
Serve all kind of file types :
var options = new FileServerOptions() {
RequestPath = PathString.Empty,
FileSystem = new PhysicalFileSystem(#"banana")
};
options.StaticFileOptions.ServeUnknownFileTypes = true;
app.UseFileServer(options);
Add woff2 mime type :
var options = new FileServerOptions() {
RequestPath = PathString.Empty,
FileSystem = new PhysicalFileSystem(#"banana")
};
((FileExtensionContentTypeProvider)options.StaticFileOptions.ContentTypeProvider)
.Mappings.Add(".woff2", "application/font-woff2");
app.UseFileServer(options);
Second options seems not as elegant but is nonetheless the best. Read why mime types are important.

You can avoid the not-very-nice casting by using inheritance:
FileServerOptions options = new FileServerOptions
{
StaticFileOptions =
{
ContentTypeProvider = new CustomFileExtensionContentTypeProvider(),
}
};
where
private class CustomFileExtensionContentTypeProvider : FileExtensionContentTypeProvider
{
public CustomFileExtensionContentTypeProvider()
{
Mappings.Add(".json", "application/json");
Mappings.Add(".mustache", "text/template");
}
}

Related

Is it possible for an Asp.Net Core Web Application to be integrated with local storage?

I have the below working on local host. However when I publish to azure the connection to my network doesn't work? I guess, this is obvious - my web app doesn't have connection to my local network. My question is, is there a way to allow a connection?
try
{
var path = "//192.168.49.14/Data/18 Customer Requests/Customer Request System/Request Letters/";
//Fetch all files in the Folder (Directory).
string[] filePaths = Directory.GetFiles(Path.Combine(path));
//Copy File names to Model collection.
var localFileList = new List<FileData>();
var assocFiles = new List<FileData>();
var linkedFiles = new List<FileData>();
assocFiles = localFileList.Where(x => x.FileName.Contains(id.ToString())).ToList();
foreach (var filePath in filePaths)
{
localFileList.Add(new FileData { FileName = Path.GetFileName(filePath) });
}
assocFiles = localFileList.Where(x => x.FileName.Contains(id.ToString())).ToList();
foreach (var item in assocFiles)
{
linkedFiles.Add(new FileData { FileName = Path.GetFileName(item.FileName) });
}
ViewBag.localFiles = linkedFiles;
}
catch
{
;
}
return View(Complaint);

'ControllerBase.File(byte[], string)' is a method, which is not valid in the given context (CS0119) - in method

I am trying to create an app where user can upload a text file, and gets the altered text back.
I am using React as FE and ASP.NET Core for BE and Azure storage for the database storage.
This is how my HomeController looks like.
I created a separate "UploadToBlob" method, to post the data
public class HomeController : Controller
{
private readonly IConfiguration _configuration;
public HomeController(IConfiguration Configuration)
{
_configuration = Configuration;
}
public IActionResult Index()
{
return View();
}
[HttpPost("UploadFiles")]
//OPTION B: Uncomment to set a specified upload file limit
[RequestSizeLimit(40000000)]
public async Task<IActionResult> Post(List<IFormFile> files)
{
var uploadSuccess = false;
string uploadedUri = null;
foreach (var formFile in files)
{
if (formFile.Length <= 0)
{
continue;
}
// read directly from stream for blob upload
using (var stream = formFile.OpenReadStream())
{
// Open the file and upload its data
(uploadSuccess, uploadedUri) = await UploadToBlob(formFile.FileName, null, stream);
}
}
if (uploadSuccess)
{
//return the data to the view, which is react display text component.
return View("DisplayText");
}
else
{
//create an error component to show there was some error while uploading
return View("UploadError");
}
}
private async Task<(bool uploadSuccess, string uploadedUri)> UploadToBlob(string fileName, object p, Stream stream)
{
if (stream is null)
{
try
{
string connectionString = Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING");
// Create a BlobServiceClient object which will be used to create a container client
BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);
//Create a unique name for the container
string containerName = "textdata" + Guid.NewGuid().ToString();
// Create the container and return a container client object
BlobContainerClient containerClient = await blobServiceClient.CreateBlobContainerAsync(containerName);
string localPath = "./data/";
string textFileName = "textdata" + Guid.NewGuid().ToString() + ".txt";
string localFilePath = Path.Combine(localPath, textFileName);
// Get a reference to a blob
BlobClient blobClient = containerClient.GetBlobClient(textFileName);
Console.WriteLine("Uploading to Blob storage as blob:\n\t {0}\n", blobClient.Uri);
FileStream uploadFileStream = File.OpenRead(localFilePath);
await blobClient.UploadAsync(uploadFileStream, true);
uploadFileStream.Close();
}
catch (StorageException)
{
return (false, null);
}
finally
{
// Clean up resources, e.g. blob container
//if (blobClient != null)
//{
// await blobClient.DeleteIfExistsAsync();
//}
}
}
else
{
return (false, null);
}
}
}
but the console throws errors, saying "'ControllerBase.File(byte[], string)' is a method, which is not valid in the given context (CS0119)"
And because of this error, another error follows "'HomeController.UploadToBlob(string, object, Stream)': not all code paths return a value (CS0161)"
my questions are
Is it a better idea to create a separate method like I did?
how can I resolve the issue regarding the "File" being valid inside of the UploadToBlob method?
If I want to add the file type validation, where should it happen? t.ex. only text file is alid
If I want to read the text string from the uploaded text file, where should I call the
string contents = blob.DownloadTextAsync().Result;
return contents;
How can I pass down the "contents" to my react component? something like this?
useEffect(() => {
fetch('Home')
.then(response => response.json())
.then(data => {
setForcasts(data)
})
}, [])
Thanks for helping this super newbie with ASP.NET Core!
1) It is ok to put uploading into separate method, it could also be put into a separate class for handling blob operations
2) File is the name of one of the controllers methods, if you want to reference the File class from System.IO namespace, you need to fully qualify the name
FileStream uploadFileStream = System.IO.File.OpenRead(localFilePath);
To the other compile error, you need to return something from the UploadToBlob method, now it does not return anything from the try block
3) File type validation can be put into the controller action method
4) it depends on what you plan to do with the text and how are you going to use it. Would it be a new action of the controller (a new API endpoint)?
5) you could create a new API endpoint for downloading files
UPDATE:
For word replacement you could use a similar method:
private Stream FindMostFrequentWordAndReplaceIt(Stream inputStream)
{
using (var sr = new StreamReader(inputStream, Encoding.UTF8)) // what is the encoding of the text?
{
var allText = sr.ReadToEnd(); // read all text into memory
// TODO: Find most frequent word in allText
// replace the word allText.Replace(oldValue, newValue, stringComparison)
var resultText = allText.Replace(...);
var result = new MemoryStream();
using (var sw = new StreamWriter(result))
{
sw.Write(resultText);
}
result.Position = 0;
return result;
}
}
it would be used in your Post method this way:
using (var stream = formFile.OpenReadStream())
{
var streamWithReplacement = FindMostFrequentWordAndReplaceIt(stream);
// Upload the replaced text:
(uploadSuccess, uploadedUri) = await UploadToBlob(formFile.FileName, null, streamWithReplacement);
}
You probably have this method inside MVC controller in which File method exists. Add in your code System.IO.File instead of File

Asp.net core file upload with Graphql-dotnet

I am trying to upload an image file with graphql-dotnet, but it is never successful.
I am taking file object in my GraphQLController:
var files = this.Request.Form.Files;
var executionOptions = new ExecutionOptions
{
Schema = _schema,
Query = queryToExecute,
Inputs = inputs,
UserContext = files,
OperationName = query.OperationName
};
And here my Mutation:
Field<UserGraphType>(
"uploadUserAvatar",
Description="Kullanıcı resmi yükleme.",
arguments: new QueryArguments(
new QueryArgument<NonNullGraphType<IntGraphType>> { Name = "Id", Description = "Identity Alanı" }
),
resolve: context => {
var file = context.UserContext.As<IFormCollection>();
var model = userService.UploadAvatar(context.GetArgument<int>("Id"),file);
return true;
}
);
I think it is accepting the only JSON. It is not accepting the request as a file type.
Also I am using React & apollo-client at the client-side. It has an error in the console:
Failed to load http://localhost:5000/graphql: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 500. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I am trying to send the query like this:
const { selectedFile,id } = this.state
this.props.uploadAvatar({
variables: {id},
file:selectedFile
}).then(result => {
console.log(result);
});
What can I do to achieve this?
Failed to load http://localhost:5000/graphql: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8080' is therefore not allowed
access.
This error means you need to enable CORS.
See these docs: https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1
Essentially you need these two things:
services.AddCors();
app.UseCors(builder =>
builder.WithOrigins("http://example.com"));
I would also suggest to look at this Deserializer helper function in the GraphQL.Relay project. It helps your server handle a multipart/form-data request. You can then use the parsed query information and files and pass it to the DocumentExecutor.
https://github.com/graphql-dotnet/relay/blob/master/src/GraphQL.Relay/Http/Deserializer.cs
public static class Deserializer
{
public static async Task<RelayRequest> Deserialize(Stream body, string contentType)
{
RelayRequest queries;
switch (contentType)
{
case "multipart/form-data":
queries = DeserializeFormData(body);
break;
case "application/json":
var stream = new StreamReader(body);
queries = DeserializeJson(await stream.ReadToEndAsync());
break;
default:
throw new ArgumentOutOfRangeException($"Unknown media type: {contentType}. Cannot deserialize the Http request");
}
return queries;
}
private static RelayRequest DeserializeJson(string stringContent)
{
if (stringContent[0] == '[')
return new RelayRequest(
JsonConvert.DeserializeObject<RelayQuery[]>(stringContent),
isBatched: true
);
if (stringContent[0] == '{')
return new RelayRequest() {
JsonConvert.DeserializeObject<RelayQuery>(stringContent)
};
throw new Exception("Unrecognized request json. GraphQL queries requests should be a single object, or an array of objects");
}
private static RelayRequest DeserializeFormData(Stream body)
{
var form = new MultipartFormDataParser(body);
var req = new RelayRequest()
{
Files = form.Files.Select(f => new HttpFile {
ContentDisposition = f.ContentDisposition,
ContentType = f.ContentType,
Data = f.Data,
FileName = f.FileName,
Name = f.Name
})
};
req.Add(new RelayQuery {
Query = form.Parameters.Find(p => p.Name == "query").Data,
Variables = form.Parameters.Find(p => p.Name == "variables").Data.ToInputs(),
});
return req;
}
}

webapi MVC4 how to get folder files directory to display data

hi guys i able to get the data from my database API. but how do i get the folder files directory example /upload/activity/ ??
public class APIActivityController : ApiController
{
// var files = db.activities.GetFiles().ToList();
private istellarEntities db = new istellarEntities();
public IList<activity2> GetAllCategories()
{
IList<activity> lstAct = db.activities.ToList();
List<activity2> lstReturnList = new List<activity2>();
foreach (activity a in lstAct)
{
Models.activity2 act = new activity2();
act.ActivityID = a.ActivityID;
act.ActivityName = a.ActivityName;
act.Description = a.Description;
act.ImageURL = a.ImageURL;
lstReturnList.Add(act);
}
return lstReturnList;
}
// var files = db.activities.GetFiles().ToList();
static void DirSearch(string sDir)
here is my code, but i am missing something to get the list of directories any help guys? i know i shouldn't use void, maybe a list instead??
try
{
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d))
{
Console.WriteLine(f);
}
DirSearch(d);
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
To get the physical folder path of a virtual path from your code like /upload/activity you can use the following code
string pathToFiles = Server.MapPath("/upload/activity");

Scala Lift - Save uploaded files to server directory

I'm currently storing images within the webapp folder of my Lift project, which I know will cause problems in future.
val path = "src/main/webapp/files/"
And the code I'm using to save it:
case Full(file) =>
val holder = new File(path, "test.txt")
val output = new FileOutputStream(holder)
try {
output.write(file)
} finally {
output.close()
}
}
What I'm trying to do is save the to the server root in an easily manageable folder called files, so SERVER_ROOT/files outside of the project folder.
Firstly how would I access the path to the root of the server so I can save them there?
Secondly how would I serve these files from my app, so I can display them on a page?
Thanks in advance, any help much appreciated :)
You have to store file to exact place on filesystem according to absolute path. I have written this code and it works, so maybe it helps you:
def storeFile (file : FileParamHolder): Box[File] =
{
getBaseApplicationPath match
{
case Full(appBasePath) =>
{
var uploadDir = new File(appBasePath + "RELATIVE PATH TO YOUR UPLOAD DIR")
val uploadingFile = new File(uploadDir, file.fileName)
println("upload file to: " + uploadingFile.getAbsolutePath)
var output = new FileOutputStream(uploadingFile)
try
{
output.write(file.file)
}
catch
{
case e => println(e)
}
finally
{
output.close
output = null
}
Full(uploadingFile)
}
case _ => Empty
}
}
and this is my getBaseApplicationPath function which finds out absolute path of local machine (server or your devel PC):
def getBaseApplicationPath: Box[String] =
{
LiftRules.context match
{
case context: HTTPServletContext =>
{
var baseApp: String = context.ctx.getRealPath("/")
if(!baseApp.endsWith(File.separator))
baseApp = baseApp + File.separator
Full(baseApp)
}
case _ => Empty
}
}

Resources