How to fix issue "IOException: Read-only file system" ASP.NET Core in Azure App Service with linux os? - azure

I deploy a web app based on ASP.NET Core to Azure with Visual Studio 2019. Everything is ok except the upload images feature that actually accesses to folder/file. Thanks a lot for your suggestions.
public string UploadFile(IFormFile image)
{
if (image == null) return null;
try
{
string fileName = Guid.NewGuid().ToString() + image.FileName;
string filePath = Path.Combine(_hostingEnvironment.WebRootPath, "Images", "ProductImages", fileName);
var extension = new[] { "image/jpg", "image/png", "image/jpeg" };
if (!extension.Contains(image.ContentType))
return null;
using (FileStream file = new FileStream(filePath, FileMode.Create))
{
image.CopyTo(file);
}
return fileName;
}
catch (Exception ex)
{
throw;
}
}
Error:
An unhandled exception occurred while processing the request.
IOException: Read-only file system

I have test your code and found it works fine in local. So I try to deploy this app to azure webapp (linux platform).
And also encountered this situation. So I check the application settings in azure portal.
Solution
Delete WEBSITES_RUN_FROM_PACKAGE option at application settings in azure portal.
Why and How to solve it
Maybe there are some settings in publishsettings file cause the issue, you can download the publishsettings from azure portal.
And import into your IDE (like vs2019), or you can try to use another pc to deploy the app to prevent generate WEBSITES_RUN_FROM_PACKAGE.

add FileAccess Permission
FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);

Related

Need help to develop simple Sharepoint 2013 app to upload excel files to a library

I spun up a new windows 2012 Server R2, installed Sharepoint 2013, and Visual Studio 2019 with the Office/Sharepoint dev options on an old Dell server. I'm trying to write and debug an app I found on the web to upload excel files from a shared drive to a sharepoint document library. I'm at the point where everytime I try to run this app, I get an error stating:
The Web application at http://tcaserver01/my/MPR could not be found.
Verify that you have typed the URL correctly. If the URL should be
serving existing content, the system administrator may need to add a
new request URL mapping to the intended application.
I just need a bit of hand-holding to get things properly configured I think. However, when I put in the url in a web browser, it shows the empty library fine.
using System;
using System.IO;
using Microsoft.SharePoint;
namespace SPTest2
{
class Program
{
[STAThread]
static int Main(string[] args)
{
String site = "http://tcaserver01/my/MPR"; //URL of SharePoint site
String library = "Review_Workbooks"; //Library Name
String filePath = #"S:\MPR\MPR Template.xlsx"; //Entire path of file to upload
try
{
using (SPSite spSite = new SPSite(site))
{
using (SPWeb spWeb = spSite.OpenWeb())
{
//Check if file exists in specified path
if (!System.IO.File.Exists(filePath))
Console.WriteLine("Error - Specified file not found.");
//Get handle of library
SPFolder spLibrary = spWeb.Folders[library];
//Extract file name (file will be uploaded with this name)
String fileName = System.IO.Path.GetFileName(filePath);
//Read file for uploading
FileStream fileStream = File.OpenRead(filePath);
//Replace existing file
Boolean replaceExistingFile = true;
//Upload document to library
SPFile spfile = spLibrary.Files.Add(fileName, fileStream, replaceExistingFile);
spfile.CheckIn("file uploaded via code");
spLibrary.Update();
}
}
Console.WriteLine("File uploaded successfully !!");
Console.ReadLine();
}
catch (Exception exp)
{
Console.WriteLine("Error uploading file - " + exp.Message);
Console.ReadLine();
}
return 0;
}
}
}
Well, it seems when I logged in as the Sharepoint admin user account, I was able to move further in the app, successfully opening up the Sharepoint site. So, when I was logged in as myself, I must not have had the appropriate permissions to open the site. So, this question should be closed as I can now get past what was blocking me. Thanks for anyone who may have read this question already!

How to store file into inetpub\wwwroot instead of local machine folder on UWP application

I am currently developing a UWP application for my school project and one of the pages allows the user to take a picture of themselves. I created the feature by following this tutorial: CameraStarterKit
For now I am storing the pictures taken on my desktop's picture folder. But the requirement of my project is to store the pictures taken in a folder called "Photos" under inetpub\wwwroot.
I dont really understand what wwwroot or IIS is... hence, I have no idea how I should modify my codes and store them into the folder.
Here are my codes for storing on my local desktop:
private async Task TakePhotoAsync()
{
idleTimer.Stop();
idleTimer.Start();
var stream = new InMemoryRandomAccessStream();
//MediaPlayer mediaPlayer = new MediaPlayer();
//mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/camera-shutter-click-03.mp3"));
//mediaPlayer.Play();
Debug.WriteLine("Taking photo...");
await _mediaCapture.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), stream);
try
{
var file = await _captureFolder.CreateFileAsync("NYPVisitPhoto.jpg", CreationCollisionOption.GenerateUniqueName);
Debug.WriteLine("Photo taken! Saving to " + file.Path);
var photoOrientation = CameraRotationHelper.ConvertSimpleOrientationToPhotoOrientation(_rotationHelper.GetCameraCaptureOrientation());
await ReencodeAndSavePhotoAsync(stream, file, photoOrientation);
Debug.WriteLine("Photo saved!");
}
catch (Exception ex)
{
// File I/O errors are reported as exceptions
Debug.WriteLine("Exception when taking a photo: " + ex.ToString());
}
}
For the storing of the files:
private static async Task ReencodeAndSavePhotoAsync(IRandomAccessStream stream, StorageFile file, PhotoOrientation photoOrientation)
{
using (var inputStream = stream)
{
var decoder = await BitmapDecoder.CreateAsync(inputStream);
using (var outputStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateForTranscodingAsync(outputStream, decoder);
var properties = new BitmapPropertySet { { "System.Photo.Orientation", new BitmapTypedValue(photoOrientation, PropertyType.UInt16) } };
await encoder.BitmapProperties.SetPropertiesAsync(properties);
await encoder.FlushAsync();
}
}
}
I would add an answer since there are tricky things about this requirement.
The first is the app can only access a few folders, inetpub is not one of them.
Using brokered Windows runtime component (I would suggest using FullTrustProcessLauncher, which is much simpler to develop and deploy) can enable UWP apps access folders in the same way as the traditional desktop applications do.
While this works for an ordinary folder, the inetpub folder, however, is different that it requires Administrators Privileges to write to, unless you turn UAC off.
The desktop component launched by the app does not have the adequate privileges to write to that folder, either.
So it think an alternative way would be setting up a virtual directory in IIS manager that maps to a folder in the public Pictures library, and the app saves picture to that folder.
From the website’s perspective, a virtual directory is the same as a real folder under inetpub, what differs is the access permissions.
Kennyzx is right here that you cannot access inetpub folder through your UWP application due to permissions.
But if your application fulfills following criteria then you can use Brokered Windows Component(a component within your app) to copy your file to any location in the system.
Your application is a LOB application
You are only targetting desktop devices(I assume this will be true because of your requirement)
You are using side-loading for your app installation and distribution.
If all three are Yes then use Brokered Windows Component for UWP, it's not a small thing that can be showed here on SO using an example. So give worth a try reading and implementing it.

MVC5 File Upload and Display

I am currently having an issue with an MVC application that uploads a image to a file server.
public ActionResult UploadFile(HttpPostedFileBase file, string newFileName)
{
try
{
if (file.ContentLength > 0)
{
Bitmap bm = new Bitmap(file.InputStream);
Bitmap final = new Bitmap(bm, 150, 150);
final.SetResolution(72.0F, 72.0F);
string _FileName = newFileName + ".jpg";
string _path = Path.Combine(ConfigurationManager.AppSettings["imageDirectory"], _FileName);
final.Save(_path,System.Drawing.Imaging.ImageFormat.Jpeg);
}
ViewBag.Message = "File Uploaded Successfully!!";
return RedirectToAction("Index");
}
catch
{
ViewBag.Message = "File upload failed!!";
return RedirectToAction("Error");
}
}
So the user chooses a file and uploads it to the to the Windows share. This code works on my machine using IISExpress and on our Test server. When deployed to our Production server, it appears to be working in that it redirects to Index but the file never changes on the File Server.
IISExpress, the Test server, and the Production Server all point to the same file directory too.
Another issue I ran into while troubleshooting this is that the image from the file server does not display when using the FQDN of the application. So http://[appName].[domain].[com] cannot display pictures, but http://[appName] does display the image. Just another weird issue, that did not show up in testing at all.
Here is the problem and solution;
If it works on your development system then the problem is that you did not give readwrite access to app_data folder. HttpPostedFileBase always upload file temporarily into App_Store and its from there that your Save() method takes the file from. If you don't have App_Data folder, create it. You must give full ReadWrite access to IIS_USERS on your server

Why am I getting an UnauthorizedAccessException when trying to write a file to LocalStorage in Azure

I have created a local storage in my web role called "MyTestCache" as so in my
ServiceDefinition.csdef file. But when ever I call the System.IO.File.WriteAllBytes method I get a UnauthorizedAccess exception. Does anyone know what would be causing this? I dont get this when creating the directory in the code below, only when writing. I am using SDK 1.3.
private void SaveFileToLocalStorage(byte[] remoteFile, string filePath)
{
try
{
LocalResource myIO = RoleEnvironment.GetLocalResource("MyTestCache");
// Creates directory if it doesn't exist (ie the first time)
if (!Directory.Exists(myIO.RootPath + "/thumbnails"))
{
Directory.CreateDirectory(myIO.RootPath + "/thumbnails");
}
string PathToFile = Path.Combine(myIO.RootPath + "/thumbnails", filePath);
var path = filePath.Split(Char.Parse("/"));
// Creates the directory for the content item (GUID)
if (!Directory.Exists(Path.Combine(myIO.RootPath + "/thumbnails", path[0])))
{
Directory.CreateDirectory(Path.Combine(myIO.RootPath + "/thumbnails", path[0]));
}
// Writes the file to local storage.
File.WriteAllBytes(PathToFile, remoteFile);
}
catch (Exception ex)
{
// do some exception handling
return;
}
}
Check ACLs. In SDK 1.3 by default web roles are started in full IIS worker process, using Network Service as identity of application pool. Make sure Network Service account has permissions to execute operations you expect. In your case you are trying to create a sub-directory, so most probably you need at least Write permission. If your role also modifies ACLs on this directory, you need to grant Full access to this directory.

azure reading mounted VHD

I am developing "azure web application".
I have created drive and drivePath static members in WebRole as follows:
public static CloudDrive drive = null;
public static string drivePath = "";
I have created development storage drive in WebRole.OnStart as follows:
LocalResource azureDriveCache = RoleEnvironment.GetLocalResource("cache");
CloudDrive.InitializeCache(azureDriveCache.RootPath, azureDriveCache.MaximumSizeInMegabytes);
CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
{
// for a console app, reading from App.config
//configSetter(ConfigurationManager.AppSettings[configName]);
// OR, if running in the Windows Azure environment
configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
});
CloudStorageAccount account = CloudStorageAccount.DevelopmentStorageAccount;
CloudBlobClient blobClient = account.CreateCloudBlobClient();
blobClient.GetContainerReference("drives").CreateIfNotExist();
drive = account.CreateCloudDrive(
blobClient
.GetContainerReference("drives")
.GetPageBlobReference("mysupercooldrive.vhd")
.Uri.ToString()
);
try
{
drive.Create(64);
}
catch (CloudDriveException ex)
{
// handle exception here
// exception is also thrown if all is well but the drive already exists
}
string path = drive.Mount(azureDriveCache.MaximumSizeInMegabytes, DriveMountOptions.None);
IDictionary<String, Uri> listDrives = Microsoft.WindowsAzure.StorageClient.CloudDrive.GetMountedDrives();
drivePath = path;
The drive keeps visible and accessible till execution scope remain in WebRole.OnStart, as soon as execution scope leave WebRole.OnStart, drive become unavailable from application and static members get reset (such as drivePath get set to "")
Am I missing some configuration or some other error ?
Where's the other code where you're expecting to use drivePath? Is it in a web application?
If so, are you using SDK 1.3? In SDK 1.3, the default mode for a web application is to run under full IIS, which means running in a separate app domain from your RoleEntryPoint code (like OnStart), so you can't share static variables across the two. If this is the problem, you might consider moving this initialization code to Application_Begin in Global.asax.cs instead (which is in the web application's app domain).
I found the solution:
In development machine, request originate for localhost, which was making the system to crash.
Commenting "Sites" tag in ServiceDefinition.csdef, resolves the issue.

Resources