简体   繁体   中英

Reading static files on ASP.NET

I'm on a solution with multiple projects, and I'm having issues accessing a project outside the one I'm currently on. Here's a very simplified structure of my codebase:

-ProjectA
     -Pages
          Index.razor
-ProjectB
    - Images
          -image.jpg

I'm on ProjectA using Blazor Server and I need to read an image outside my directory in ProjectB. I created a static file using the following code:

app.UseStaticFiles(new StaticFileOptions()
        {
            FileProvider = new PhysicalFileProvider(
             Path.Combine(Directory.GetCurrentDirectory(), @"./../ProjectB/Images/")),
            RequestPath = new PathString("/MyImages")
        });

The thing is, when I use "/MyImages" inside of an html img tag followed with the filename, it works fine and I can view any image in ProjectB. However, this does not work when I'm using System.IO code such as:

@code{
File.ReadAllBytes("/MyImages/image.jpg");
}

Can someone let me know what I'm doing wrong?

EDIT: I should have been a bit more clearer on the purpose of my project.

I have three classes that I'm dealing with, Product , CreateProduct and EditProduct . Those classes have the same properties like Name, Price, etc . The only difference is that Product has the string ImagePath while CreateProduct and EditProduct have IFormFile Image .

When I want to create a new Product, I read the string values like name, price, etc, then for the image, I use InputFile which gives me a IBrowserFile , do some basic conversion process to an IFormFile then POST it as a CreateProduct . In the backend, the API will store the IFormFile in the file system (aka ProjectB) then create a Product record in the DB which has the ImagePath.

Here's the snippet of code for this process:

[HttpPost]
    public async Task<ActionResult<Product>> PostProduct([FromForm] CreateProduct model)
    {
        try
        {
            if (!ModelState.IsValid)
                return BadRequest();
            // This function helpers.UploadFiles will just write the file to the file system, then return the url
           // For example, it'll return "/product_1/image.jpg"
            var ProductImagePath = await _helpers.UploadFiles(model.Image);

            var product = new Product
            {
                //news
                Name = model.Name,
                Price = model.Price,
                ImagePath = ProductImagePath,
                CreatedDate = DateTime.Now
            };
            _context.Product.Add(Product);
            await _context.SaveChangesAsync();

And this is how it looks on the frontend:

// Converting my IBrwserFile(imageFile) to bytes so that it can be posted as IForm (Probably could do it better but that's an issue for another day)
using Stream filestream = imageFile.OpenReadStream(1024 * 1024 * 15);
using MemoryStream ms = new();
await filestream.CopyToAsync(ms);
byte[] productImage = ms.ToArray();


var formContent = new MultipartFormDataContent
    {
         {new StringContent("SomeProductName"),"Name"},
         {new StringContent("SomeProductPrice"),"Price" },
         {
            new ByteArrayContent(productImage), "Image", fileName
         },
    };
                await client.PostAsync("Product/", formContent);

My PUT request follows the same structure. The tricky part is the EditProduct scenario. I first have to do a GET request and receive the Product instance which only has the image path. There are two scenarios that editing my product entails:

Scenario 1:

1- Make a GET request for the `Product` class which has the image path
2- View all information including the image on the browser using <img src="ImagePath">
3- Decide to use a different image, which then I just call InputFile
4- Process InputFile and convert it to IFormFile
5- Make a PUT request and post the updated information to `EditForm` class

This works out fine. However in Scenario 2:

1- Steps 1 & 2 as before
2- Decide not to change the image, but change other stuff like the Name and price
3- ????

Now I need to make a PUT request but since I didn't use InputFile, I don't have an IFormFile that I can send to the PUT request for EditForm class. In order for the PUT process to work properly, I need to read the image I got from the ImagePath using File.ReadAllBytes then read it to memory and convert it to an IFormFile .

As I mentioned at the start I can view the image using <img src="/MyImages/@imagePath /> , with /MyImages being the static file path I created on Startup.cs. That doesn't work when I apply it to File.ReadAllBytes or any other IO functions.

It seems to me that your two projects are compiled under different folder systems, but are hosted under the same domain (say, "localhost/A" and "localhost/B"). From your browser's point of view, there's no problem.

But if you are trying to access files in your physical system, there's a problem because they have different root paths, and aren't actually sharing any folders. (which is as it should be, since you don't want 2 apps struggling for control over the file system)

Why do you want direct access to the image files? Will you manipulate them from your other project somehow?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM