Файл используется другим процессом, ошибка при загрузке файла с использованием сервера, но не локального хоста
Я довольно новичок в MVC и.NET, и я столкнулся с моей первой проблемой, на которой я застрял в течение 3 дней. Я прошу прощения за длинный пост.
Часть проекта, над которым я работаю, требует, чтобы пользователь мог выбрать файл XLS или XLSX и загрузить его, чтобы данные могли быть импортированы приложением. Вероятно, загружаемые файлы будут иметь более 20000 строк данных.
У меня есть тестовые файлы с 5000, 10000 и 20000 строк в них. Когда я запускаю свое приложение на локальном компьютере (с использованием Visual Studio 2010), все эти файлы сохраняются в сетевой папке и обрабатываются очень хорошо. Нет ошибок Однако при развертывании приложения на нашем сервере разработки через 5 минут я получаю сообщение об ошибке, что файл 10k и 20k не может быть доступен, поскольку он используется другим процессом.
Сообщение об ошибке: процесс не может получить доступ к файлу "удалил эту часть пути \TestBook-10k-rows.xlsx", так как он используется другим процессом.
Трассировки стека:
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy)
at System.IO.FileStream..ctor(String path, FileMode mode)
at System.Web.HttpPostedFile.SaveAs(String filename)
at System.Web.HttpPostedFileWrapper.SaveAs(String filename)
at edtStar.Controllers.TableController.Import(HttpPostedFileBase UploadFile, FormCollection collection) in <removed this part of the path>\TableController.cs:line 392
Размер файла 10000 составляет 304 КБ, и в моем файле web.config установлены следующие ограничения длины:
<httpRuntime
maxRequestLength="4096"
requestLengthDiskThreshold="1024"/>
Я не могу найти ничего особенного около 5 минут, но он всегда возвращает ошибку через 5 минут после начала загрузки.
Я пробовал это с Chrome и IE. Оба работают через localhost, ни один не работает через наш сервер приложений dotnet.
Трассировка стека говорит о том, что метод SaveAs() разрушен, но я вижу файл в сетевой папке и размер совпадает.
После сохранения файла я должен прочитать его и вернуть данные в новое представление. Перед возвратом их в представление выполняется довольно много обработки данных, и я ожидаю, что это будет 5 или более минут. После завершения чтения файла я закрываю соединение и удаляю файл из общего сетевого ресурса. Файл также удаляется вскоре после получения исключения. Файл не существует, когда я начинаю каждую загрузку.
Я единственный человек, работающий с этим приложением прямо сейчас, так как оно все еще находится в разработке. Я не верю, что кто-то еще получает доступ к сохраненной копии на общем сетевом ресурсе, пока я выполняю тестирование. Я могу последовательно воспроизвести эту проблему, но я понятия не имею, почему это происходит.
Кто-нибудь видел что-нибудь подобное или есть предложения для меня? Я предполагаю, что где-то на нашем сервере приложений есть настройка, но я не смог ее точно определить.
Спасибо!
Редактировать:
Вот код, который обрабатывает загрузку файла.
// Validate, save, and read the selected file.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Import(HttpPostedFileBase UploadFile, FormCollection collection)
{
// Do some initial file validation - removed
string filePath = Path.Combine(EDTConstants.NETWORK_SHARE_PATH, Path.GetFileName(UploadFile.FileName));
try
{
// Do some validation on the file that was uploaded.
if (UploadFile == null)
{
// return an error here - there was no file selected.
}
if (UploadFile.ContentLength == 0)
{
// return an error here - the file is empty.
}
if (!filePath.ToUpper().EndsWith("XLS") && !filePath.ToUpper().EndsWith("XLSX"))
{
// return an error here - the file extension is not supported.
}
// Things are good so far. Save the file so we can read from it.
UploadFile.SaveAs(filePath);
DataSet fileDS = new DataSet();
string connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties=\"Excel 12.0;HDR=YES;\"";
using (OleDbConnection conn = new OleDbConnection(connString))
{
conn.Open();
using (DataTable dtExcel = conn.GetSchema("Tables"))
{
// ... a bunch of code removed ...
}
conn.Close();
}
CloseFile(filePath);
}
catch (Exception e)
{
// Unexpected error
EDTUtils.LogErrorMessage(EDTConstants.TABLE_IMPORT, User.Identity.Name, e);
ViewData[EDTConstants.SSN_VD_ERROR_MSG] = EDTConstants.EM_UNEXPECTED + System.Environment.NewLine + e.Message;
ViewData[EDTConstants.VIEWDATA_FILE] = UploadFile.FileName;
CloseFile(filePath);
return View(tab);
}
// Closes a file - logs errors but does not throw any exceptions.
private void CloseFile(string filePath)
{
try
{
System.IO.File.Delete(filePath);
}
catch (IOException ioe)
{
EDTUtils.LogErrorMessage(EDTConstants.TABLE_IMPORT, User.Identity.Name, ioe);
}
}
Я вижу ту же ошибку в журнале, один раз при выполнении SaveAs() и затем снова при выполнении удаления. Это странно, однако, файл исчезает. Как будто на сервере приложений есть другой поток, пытающийся что-то сделать во время этого процесса, а на локальном хосте этого не происходит.
редактировать
После того как я изменил значение executeTimeout, я заметил, что Chrome сказал "Загрузка 79%..." через 5 минут, затем файл исчез в общем сетевом ресурсе, затем снова появился, а затем через минуту или две Chrome сказал, что страница было недоступно с кодом ошибки: ERR_INVALID_RESPONSE. Файл еще не был удален из общего сетевого ресурса. В IE меня просят снова войти в приложение через 5 минут.
1 ответ
Значение maxRequestLength указывается в КБ, но requestLengthDiskThreshold указывает ограничение для порога буферизации входного потока в байтах.
Поэтому вам нужно изменить requestLengthDiskThreshold на 543744 (531KB x 1024)
Также проверьте любой из следующих параметров, применимых к вашему сценарию.
<httpRuntime
executionTimeout = "HH:MM:SS"
maxRequestLength = "number"
requestLengthDiskThreshold = "number"
useFullyQualifiedRedirectUrl = "[True|False]"
minFreeThreads = "number"
minLocalRequestFreeThreads = "number"
appRequestQueueLimit = "number"
enableKernelOutputCache = "[True|False]"
enableVersionHeader = "[True|False]"
apartmentThreading = "[True|False]"
requireRootedSaveAsPath = "[True|False]"
enable = "[True|False]"
sendCacheControlHeader = "[True|False]"
shutdownTimeout = "HH:MM:SS"
delayNotificationTimeout = "HH:MM:SS"
waitChangeNotification = "number"
maxWaitChangeNotification = "number"
enableHeaderChecking = "[True|False]"
/>
Возможно, для запроса происходит тайм-аут, и файл сохраняется процессом загрузки и в следующей попытке все еще занят.
Я советую вам удалить любой из загруженных файлов, перезапустить пул приложений, установить значение executeTimeout в настройках httpRuntime и повторить попытку.
Подробная информация о настройках httpRuntime находится здесь http://msdn.microsoft.com/en-us/library/e1f13641%28v=vs.85%29.aspx
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Import(HttpPostedFileBase UploadFile, FormCollection collection)
{
// Do some initial file validation - removed
string filePath = Path.Combine(EDTConstants.NETWORK_SHARE_PATH, Path.GetFileName(UploadFile.FileName));
try
{
// Do some validation on the file that was uploaded.
if (UploadFile == null)
{
// return an error here - there was no file selected.
}
if (UploadFile.ContentLength == 0)
{
// return an error here - the file is empty.
}
if (!filePath.ToUpper().EndsWith("XLS") && !filePath.ToUpper().EndsWith("XLSX"))
{
// return an error here - the file extension is not supported.
}
// Things are good so far. Save the file so we can read from it.
UploadFile.SaveAs(filePath);
DataSet fileDS = new DataSet();
string connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties=\"Excel 12.0;HDR=YES;\"";
using (OleDbConnection conn = new OleDbConnection(connString))
{
conn.Open();
using (DataTable dtExcel = conn.GetSchema("Tables"))
{
// ... a bunch of code removed ...
}
conn.Close();
}
}
catch (Exception e)
{
// Unexpected error
EDTUtils.LogErrorMessage(EDTConstants.TABLE_IMPORT, User.Identity.Name, e);
ViewData[EDTConstants.SSN_VD_ERROR_MSG] = EDTConstants.EM_UNEXPECTED + System.Environment.NewLine + e.Message;
ViewData[EDTConstants.VIEWDATA_FILE] = UploadFile.FileName;
}
finally
{
CloseFile(filePath);
}
//you were only returning in the CATCH ?
return View(tab);
}
Также убедитесь, что ANTIVIRUS не пытается сканировать файлы, которые вы только что загрузили