Работа с файлами на сайте веб-страницы ASP.NET (Razor)
; автор — Том ФитцМакен (Tom FitzMacken)
В этой статье объясняется, как читать, записывать, добавлять, удалять и отправлять файлы на сайте веб-страницы ASP.NET (Razor).
Примечание
Если вы хотите отправить изображения и управлять ими (например, перевернуть или изменить их размер), см. статью Работа с изображениями на веб-страницы ASP.NET сайте.
Из этого руководства вы узнаете, как выполнять такие задачи:
- Как создать текстовый файл и записать в него данные.
- Добавление данных в существующий файл.
- Чтение и отображение файла из него.
- Удаление файлов с веб-сайта.
- Как разрешить пользователям отправлять один или несколько файлов.
Ниже приведены ASP.NET функции программирования, представленные в этой статье:
- Объект
File
, предоставляющий способ управления файлами.- Помощник
FileUpload
.- Объект
Path
, который предоставляет методы, позволяющие управлять именами путей и файлов.Версии программного обеспечения, используемые в этом руководстве
- веб-страницы ASP.NET (Razor) 2
- WebMatrix 2
Это руководство также работает с WebMatrix 3.
Создание текстового файла и запись в него данных
Помимо использования базы данных на веб-сайте, вы можете работать с файлами. Например, текстовые файлы можно использовать в качестве простого способа хранения данных для сайта. (Текстовый файл, используемый для хранения данных, иногда называют неструктурированным файлом.) Текстовые файлы могут быть разных форматов, например .txt, .xmlили .csv (значения с разделителями-запятыми).
Если вы хотите сохранить данные в текстовом файле, можно использовать File.WriteAllText
метод , чтобы указать создаваемый файл и данные для записи в него. В этой процедуре вы создадите страницу, содержащую простую форму с тремя input
элементами (имя, фамилия и адрес электронной почты) и кнопкой Отправить . Когда пользователь отправляет форму, вы сохраните введенные пользователем данные в текстовом файле.
Создайте новую папку с именем App_Data, если она еще не существует.
В корне веб-сайта создайте файл с именем UserData.cshtml.
Замените существующее содержимое следующим:
@{ var result = ""; if (IsPost) { var firstName = Request["FirstName"]; var lastName = Request["LastName"]; var email = Request["Email"]; var userData = firstName + "," + lastName + "," + email + Environment.NewLine; var dataFile = Server.MapPath("~/App_Data/data.txt"); File.WriteAllText(@dataFile, userData); result = "Information saved."; } } <!DOCTYPE html> <html> <head> <title>Write Data to a File</title> </head> <body> <form id="form1" method="post"> <div> <table> <tr> <td>First Name:</td> <td><input id="FirstName" name="FirstName" type="text" /></td> </tr> <tr> <td>Last Name:</td> <td><input id="LastName" name="LastName" type="text" /></td> </tr> <tr> <td>Email:</td> <td><input id="Email" name="Email" type="text" /></td> </tr> <tr> <td></td> <td><input type="submit" value="Submit"/></td> </tr> </table> </div> <div> @if(result != ""){ <p>Result: @result</p> } </div> </form> </body> </html>
Html-разметка создает форму с тремя текстовыми полями. В коде вы используете
IsPost
свойство , чтобы определить, была ли отправлена страница перед началом обработки.Первая задача — получить введенные пользователем данные и назначить их переменным. Затем код объединяет значения отдельных переменных в одну строку с разделителями-запятыми, которая затем сохраняется в другой переменной. Обратите внимание, что разделитель запятых — это строка, содержащаяся в кавычках (","), так как вы буквально внедряете запятую в большую строку, которую вы создаете. В конце сцепляемых данных добавьте
Environment.NewLine
. При этом добавляется разрыв строки (символ новой строки). С этим объединением вы создаете строку, которая выглядит следующим образом:David,Jones,davidj@contoso.com
(С невидимым разрывом строки в конце.)
Затем создается переменная (
dataFile
), содержащая расположение и имя файла для хранения данных. Установка расположения требует специальной обработки. На веб-сайтах не рекомендуется ссылаться в коде на абсолютные пути, такие как C:\Folder\File.txt для файлов на веб-сервере. При перемещении веб-сайта абсолютный путь будет неправильным. Кроме того, для размещенного сайта (в отличие от собственного компьютера) вы, как правило, даже не знаете, какой правильный путь при написании кода.Но иногда (как сейчас, для записи файла) требуется полный путь. Решением является использование
MapPath
методаServer
объекта . При этом возвращается полный путь к веб-сайту. Чтобы получить путь к корню веб-сайта, вы используете~
оператор (для повторного создания виртуального корня сайта) в .MapPath
(Вы также можете передать ей имя вложенной папки, например ~/App_Data/, чтобы получить путь к этой вложенной папке.) Затем можно сцепить дополнительные сведения с тем, что возвращает метод, чтобы создать полный путь. В этом примере вы добавляете имя файла. (Дополнительные сведения о работе с путями к файлам и папкам см. в статье Общие сведения о программировании веб-страницы ASP.NET с помощью синтаксиса Razor.)Файл сохраняется в папке App_Data . Эта папка представляет собой специальную папку в ASP.NET, которая используется для хранения файлов данных, как описано в разделе Общие сведения о работе с базой данных на сайтах веб-страницы ASP.NET.
Метод
WriteAllText
File
объекта записывает данные в файл. Этот метод принимает два параметра: имя (с путем) файла для записи и фактические данные для записи. Обратите внимание, что имя первого параметра имеет@
символ в качестве префикса. Это сообщает ASP.NET, что вы предоставляете буквальный строковый литерал и что такие символы, как "/", не должны интерпретироваться особыми способами. (Дополнительные сведения см. в статье Введение в веб-программирование ASP.NET с использованием синтаксиса Razor.)Примечание
Чтобы код сохранял файлы в папке App_Data , приложению требуются разрешения на чтение и запись для этой папки. На компьютере разработки это обычно не является проблемой. Однако при публикации сайта на веб-сервере поставщика услуг размещения может потребоваться явно задать эти разрешения. Если вы запускаете этот код на сервере поставщика услуг размещения и получаете ошибки, проверка с поставщиком услуг размещения, чтобы узнать, как задать эти разрешения.
Запустите страницу в браузере.
Введите значения в поля и нажмите кнопку Отправить.
Закройте браузер.
Вернитесь в проект и обновите представление.
Откройте файлdata.txt . Данные, отправленные в форме, отображаются в файле .
Закройте файлdata.txt .
Добавление данных в существующий файл
В предыдущем примере вы использовали для WriteAllText
создания текстового файла, в который входит только один фрагмент данных. Если вызвать метод еще раз и передать ему то же имя файла, существующий файл будет полностью перезаписан. Однако после создания файла часто требуется добавить новые данные в конец файла. Это можно сделать с помощью AppendAllText
метода File
объекта .
На веб-сайте создайте копию файла UserData.cshtml и назовите копию UserDataMultiple.cshtml.
Замените блок кода перед открывающим
<!DOCTYPE html>
тегом следующим блоком кода:@{ var result = ""; if (IsPost) { var firstName = Request["FirstName"]; var lastName = Request["LastName"]; var email = Request["Email"]; var userData = firstName + "," + lastName + "," + email + Environment.NewLine; var dataFile = Server.MapPath("~/App_Data/data.txt"); File.AppendAllText (@dataFile, userData); result = "Information saved."; } }
Этот код содержит одно изменение по сравнению с предыдущим примером. Вместо использования
WriteAllText
используетсяthe AppendAllText
метод . Методы аналогичны, за исключением того, чтоAppendAllText
данные добавляются в конец файла. Как и в случае сWriteAllText
,AppendAllText
создает файл, если он еще не существует.Запустите страницу в браузере.
Введите значения для полей и нажмите кнопку Отправить.
Добавьте дополнительные данные и отправьте форму еще раз.
Вернитесь в проект, щелкните правой кнопкой мыши папку проекта и выберите команду Обновить.
Откройте файлdata.txt . Теперь он содержит новые данные, которые вы только что ввели.
Чтение и отображение данных из файла
Даже если вам не нужно записывать данные в текстовый файл, иногда потребуется считывать данные из одного из них. Для этого можно снова использовать File
объект . Объект можно использовать для File
чтения каждой строки по отдельности (разделенных разрывами строк) или для чтения отдельных элементов независимо от того, как они разделены.
В этой процедуре показано, как считывать и отображать данные, созданные в предыдущем примере.
В корне веб-сайта создайте файл с именем DisplayData.cshtml.
Замените существующее содержимое следующим:
@{ var result = ""; Array userData = null; char[] delimiterChar = {','}; var dataFile = Server.MapPath("~/App_Data/data.txt"); if (File.Exists(dataFile)) { userData = File.ReadAllLines(dataFile); if (userData == null) { // Empty file. result = "The file is empty."; } } else { // File does not exist. result = "The file does not exist."; } } <!DOCTYPE html> <html> <head> <title>Reading Data from a File</title> </head> <body> <div> <h1>Reading Data from a File</h1> @result @if (result == "") { <ol> @foreach (string dataLine in userData) { <li> User <ul> @foreach (string dataItem in dataLine.Split(delimiterChar)) { <li>@dataItem</li > } </ul> </li> } </ol> } </div> </body> </html>
Код начинается с чтения файла, созданного в предыдущем примере, в переменную с именем с помощью
userData
следующего вызова метода:File.ReadAllLines(dataFile)
Код для этого находится внутри инструкции
if
. Если вы хотите прочитать файл, рекомендуется использоватьFile.Exists
метод , чтобы сначала определить, доступен ли файл. Код также проверяет, является ли файл пустым.Текст страницы содержит два
foreach
цикла, один из них вложен в другой. Внешнийforeach
цикл получает по одной строке за раз из файла данных. В этом случае строки определяются разрывами строк в файле, то есть каждый элемент данных находится в отдельной строке. Внешний цикл создает новый элемент (<li>
элемент) внутри упорядоченного списка (<ol>
элемент).Внутренний цикл разделяет каждую строку данных на элементы (поля), используя запятую в качестве разделителя. (На основе предыдущего примера это означает, что каждая строка содержит три поля : имя, фамилия и адрес электронной почты, разделенные запятой.) Внутренний цикл также создает
<ul>
список и отображает по одному элементу списка для каждого поля в строке данных.В коде показано, как использовать два типа данных: массив и
char
тип данных. Массив является обязательным, так какFile.ReadAllLines
метод возвращает данные в виде массива. Типchar
данных является обязательным, так какSplit
метод возвращает объект ,array
в котором каждый элемент имеет типchar
. (Сведения о массивах см. в статье Общие сведения о веб-программировании ASP.NET с использованием синтаксиса Razor.)Запустите страницу в браузере. Отобразятся данные, введенные для предыдущих примеров.
Совет
Отображение данных из файла Comma-Delimited Microsoft Excel
Вы можете использовать Microsoft Excel для сохранения данных, содержащихся в электронной таблице, в виде файла с разделителями-запятыми (.csv файл). При этом файл сохраняется в виде обычного текста, а не в формате Excel. Каждая строка в электронной таблице разделяется разрывом строки в текстовом файле, а каждый элемент данных отделяется запятой. Код, показанный в предыдущем примере, можно использовать для чтения файла Excel с разделителями-запятыми, просто изменив имя файла данных в коде.
Удаление файлов
Чтобы удалить файлы с веб-сайта, можно использовать File.Delete
метод . В этой процедуре показано, как разрешить пользователям удалять изображение (.jpg файл) из папки images , если они знают имя файла.
Примечание
Важно На рабочем веб-сайте обычно ограничивается, кому разрешено вносить изменения в данные. Сведения о настройке членства и способах авторизации пользователей для выполнения задач на сайте см. в статье Добавление безопасности и членства на сайт веб-страницы ASP.NET.
На веб-сайте создайте вложенную папку с именем images.
Скопируйте один или несколько файлов.jpg в папку images .
В корне веб-сайта создайте файл с именем FileDelete.cshtml.
Замените существующее содержимое следующим:
@{ bool deleteSuccess = false; var photoName = ""; if (IsPost) { photoName = Request["photoFileName"] + ".jpg"; var fullPath = Server.MapPath("~/images/" + photoName); if (File.Exists(fullPath)) { File.Delete(fullPath); deleteSuccess = true; } } } <!DOCTYPE html> <html> <head> <title>Delete a Photo</title> </head> <body> <h1>Delete a Photo from the Site</h1> <form name="deletePhoto" action="" method="post"> <p>File name of image to delete (without .jpg extension): <input name="photoFileName" type="text" value="" /> </p> <p><input type="submit" value="Submit" /></p> </form> @if(deleteSuccess) { <p> @photoName deleted! </p> } </body> </html>
Эта страница содержит форму, в которой пользователи могут ввести имя файла изображения. Они не вводят расширение имени файла.jpg ; Ограничивая имя файла, как это, вы помогаете запретить пользователям удалять произвольные файлы на вашем сайте.
Код считывает имя файла, введенное пользователем, а затем создает полный путь. Для создания пути в коде используется текущий путь к веб-сайту (возвращаемый методом
Server.MapPath
), имя папки images , указанное пользователем имя и ".jpg" в виде литеральной строки.Чтобы удалить файл, код вызывает
File.Delete
метод , передав ему только что созданный полный путь. В конце разметки код отображает сообщение с подтверждением удаления файла.Запустите страницу в браузере.
Введите имя удаляемого файла и нажмите кнопку Отправить. Если файл был удален, имя файла отображается в нижней части страницы.
Предоставление пользователям возможности отправлять файлы
Вспомогательное FileUpload
средство позволяет пользователям отправлять файлы на ваш веб-сайт. В приведенной ниже процедуре показано, как разрешить пользователям отправлять один файл.
Добавьте библиотеку веб-помощников ASP.NET на веб-сайт, как описано в разделе Установка вспомогательных служб на сайте веб-страницы ASP.NET, если вы не добавили ее ранее.
В папке App_Data создайте новую папку и назовите ее UploadedFiles.
В корневом каталоге создайте файл с именем FileUpload.cshtml.
Замените существующее содержимое на странице следующим:
@using Microsoft.Web.Helpers; @{ var fileName = ""; if (IsPost) { var fileSavePath = ""; var uploadedFile = Request.Files[0]; fileName = Path.GetFileName(uploadedFile.FileName); fileSavePath = Server.MapPath("~/App_Data/UploadedFiles/" + fileName); uploadedFile.SaveAs(fileSavePath); } } <!DOCTYPE html> <html> <head> <title>FileUpload - Single-File Example</title> </head> <body> <h1>FileUpload - Single-File Example</h1> @FileUpload.GetHtml( initialNumberOfFiles:1, allowMoreFilesToBeAdded:false, includeFormTag:true, uploadText:"Upload") @if (IsPost) { <span>File uploaded!</span><br/> } </body> </html>
В основной части страницы используется
FileUpload
вспомогательное средство для создания поля отправки и кнопок, с которыми вы, вероятно, знакомы:Свойства, заданные для вспомогательного
FileUpload
средства, указывают, что требуется одно поле для отправки файла, а кнопка "Отправить" считывает сообщение Отправить. (Вы добавите дополнительные поля далее в этой статье.)Когда пользователь нажимает кнопку Отправить, код в верхней части страницы получает файл и сохраняет его. Объект
Request
, который обычно используется для получения значенийFiles
из полей формы, также имеет массив, содержащий отправленный файл (или файлы). Вы можете получить отдельные файлы из определенных позиций в массиве. Например, чтобы получить первый отправленный файл, вы получитеRequest.Files[0]
, чтобы получить второй файл, вы получитеRequest.Files[1]
и т. д. (Помните, что в программировании подсчет обычно начинается с нуля.)При получении отправленного файла вы помещаете его в переменную (здесь,
uploadedFile
), чтобы можно было управлять им. Чтобы определить имя отправленного файла, просто получите егоFileName
свойство. Однако, когда пользователь отправляет файл,FileName
содержит исходное имя пользователя, которое включает весь путь. Он может выглядеть так: .C:\Users\Public\Sample.txt
Однако вам не нужны все эти сведения о пути, потому что это путь на компьютере пользователя, а не для вашего сервера. Требуется просто фактическое имя файла (Sample.txt). Вы можете удалить только файл из пути с помощью
Path.GetFileName
метода , как показано ниже.Path.GetFileName(uploadedFile.FileName)
Объект
Path
— это служебная программа, которая имеет ряд подобных методов, которые можно использовать для удаления путей, объединения путей и т. д.Получив имя отправленного файла, вы можете создать новый путь для хранения отправленного файла на веб-сайте. В этом случае необходимо объединить
Server.MapPath
имена папок (App_Data/UploadedFiles) и недавно удаляемое имя файла, чтобы создать новый путь. Затем можно вызвать метод отправленного файлаSaveAs
, чтобы фактически сохранить файл.Запустите страницу в браузере.
Нажмите кнопку Обзор и выберите файл для отправки.
Текстовое поле рядом с кнопкой Обзор будет содержать путь и расположение файла.
Щелкните Отправить.
На веб-сайте щелкните правой кнопкой мыши папку проекта и выберите команду Обновить.
Откройте папку UploadedFiles . Отправленный файл находится в папке .
Предоставление пользователям возможности отправлять несколько файлов
В предыдущем примере пользователи могут отправить один файл. Но с помощью вспомогательного FileUpload
средства можно отправлять несколько файлов одновременно. Это удобно для таких сценариев, как отправка фотографий, где загрузка одного файла за раз трудоемка. (Сведения об отправке фотографий см. в статье Работа с изображениями на сайте веб-страницы ASP.NET.) В этом примере показано, как разрешить пользователям отправлять два за раз, хотя вы можете использовать один и тот же метод, чтобы отправить больше.
Добавьте библиотеку веб-помощников ASP.NET на веб-сайт, как описано в разделе Установка вспомогательных служб на сайте веб-страницы ASP.NET, если вы еще этого не сделали.
Создайте страницу с именем FileUploadMultiple.cshtml.
Замените существующее содержимое на странице следующим:
@using Microsoft.Web.Helpers; @{ var message = ""; if (IsPost) { var fileName = ""; var fileSavePath = ""; int numFiles = Request.Files.Count; int uploadedCount = 0; for(int i =0; i < numFiles; i++) { var uploadedFile = Request.Files[i]; if (uploadedFile.ContentLength > 0) { fileName = Path.GetFileName(uploadedFile.FileName); fileSavePath = Server.MapPath("~/App_Data/UploadedFiles/" + fileName); uploadedFile.SaveAs(fileSavePath); uploadedCount++; } } message = "File upload complete. Total files uploaded: " + uploadedCount.ToString(); } } <!DOCTYPE html> <html> <head><title>FileUpload - Multiple File Example</title></head> <body> <form id="myForm" method="post" enctype="multipart/form-data" action=""> <div> <h1>File Upload - Multiple-File Example</h1> @if (!IsPost) { @FileUpload.GetHtml( initialNumberOfFiles:2, allowMoreFilesToBeAdded:true, includeFormTag:true, addText:"Add another file", uploadText:"Upload") } <span>@message</span> </div> </form> </body> </html>
В этом примере вспомогателя
FileUpload
в тексте страницы настроена таким образом, чтобы пользователи по умолчанию отправили два файла. Так какallowMoreFilesToBeAdded
для параметра задано значениеtrue
, вспомогающая отображает ссылку, которая позволяет пользователю добавлять дополнительные поля отправки:Для обработки файлов, отправляемых пользователем, в коде используется тот же базовый метод, который использовался в предыдущем примере— получение файла из
Request.Files
и его сохранение. (Включая различные действия, необходимые для получения правильного имени файла и пути.) Инновация на этот раз заключается в том, что пользователь может загружать несколько файлов, и вы не знаете много. Чтобы узнать это, вы можете получитьRequest.Files.Count
.Используя это число в руке, вы можете выполнить циклическое переключение
Request.Files
, получить каждый файл по очереди и сохранить его. Если вы хотите выполнить цикл по коллекции с известным числом раз, можно использоватьfor
цикл, как показано ниже.for(int i =0; i < numFiles; i++) { var uploadedFile = Request.Files[i]; if (uploadedFile.ContentLength > 0) { fileName = Path.GetFileName(uploadedFile.FileName); // etc. }
Переменная
i
является лишь временным счетчиком, который будет переходить от нуля к заданному верхнему пределу. В этом случае верхним пределом является количество файлов. Но поскольку счетчик начинается с нуля, как это обычно для сценариев подсчета в ASP.NET, верхний предел на самом деле на один меньше, чем количество файлов. (Если отправлено три файла, их число равно нулю до 2.)Переменная
uploadedCount
суммирует все файлы, которые успешно отправлены и сохранены. Этот код учитывает вероятность того, что ожидаемый файл может не быть отправлен.Запустите страницу в браузере. В браузере отображается страница и два поля отправки.
Выберите два файла для отправки.
Щелкните Добавить другой файл. На странице отображается новое поле отправки.
Щелкните Отправить.
На веб-сайте щелкните правой кнопкой мыши папку проекта и выберите команду Обновить.
Откройте папку UploadedFiles , чтобы просмотреть успешно отправленные файлы.