Работа с файлами на сайте веб-страниц 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 элементами (имя, фамилия и адрес электронной почты) и кнопкой "Отправить ". Когда пользователь отправляет форму, вы сохраните входные данные пользователя в текстовом файле.

  1. Создайте новую папку с именем App_Data, если она еще не существует.

  2. В корне веб-сайта создайте файл с именем UserData.cshtml.

  3. Замените существующее содержимое следующим образом:

    @{
        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.

    Метод WriteAllTextFile объекта записывает данные в файл. Этот метод принимает два параметра: имя (с путем) файла для записи, а также фактические данные для записи. Обратите внимание, что имя первого параметра имеет @ символ в качестве префикса. Это указывает ASP.NET, что вы предоставляете дословный строковый литерал, и что символы, такие как "/", не должны интерпретироваться каким-либо специальным образом. (Дополнительные сведения см. в статье "Введение в ASP.NET веб-программирование с помощью синтаксиса Razor".)

    Замечание

    Чтобы код сохранял файлы в папке App_Data , приложению требуются разрешения на чтение и запись для этой папки. На компьютере разработки это обычно не проблема. Однако при публикации сайта на веб-сервере поставщика услуг размещения может потребоваться явно задать эти разрешения. Если вы запускаете этот код на сервере поставщика услуг размещения и получаете ошибки, обратитесь к поставщику услуг размещения, чтобы узнать, как задать эти разрешения.

  • Запустите страницу в браузере.

    Снимок экрана: окно браузера с полями

  • Введите значения в поля и нажмите кнопку "Отправить".

  • Закройте браузер.

  • Вернитесь в проект и обновите представление.

  • Откройте файлdata.txt . Данные, отправленные в форме, отображаются в файле.

    Снимок экрана файла данных .txt, в котором показано, что данные, введенные в поля веб-браузера, были записаны в файл .txt.

  • Закройте файл data.txt .

Добавление данных в существующий файл

В предыдущем примере вы использовали WriteAllText для создания текстового файла, который имеет только один фрагмент данных в нем. При повторном вызове метода и передаче того же имени файла существующий файл полностью перезаписан. Однако после создания файла часто требуется добавить новые данные в конец файла. Это можно сделать с помощью AppendAllText метода File объекта.

  1. На веб-сайте создайте копию файла UserData.cshtml и назовите файл userDataMultiple.cshtml.

  2. Замените блок кода перед открывающим <!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 создает файл, если он еще не существует.

  3. Запустите страницу в браузере.

  4. Введите значения полей и нажмите кнопку "Отправить".

  5. Добавьте дополнительные данные и снова отправьте форму.

  6. Вернитесь к проекту, щелкните правой кнопкой мыши папку проекта и нажмите кнопку "Обновить".

  7. Откройте файлdata.txt . Теперь он содержит новые данные, которые вы только что ввели.

    Снимок экрана файла data.txt, показывающий, что данные, введенные в поля веб-браузера, были записаны без перезаписи предыдущих данных.

Чтение и отображение данных из файла

Даже если вам не нужно записывать данные в текстовый файл, иногда потребуется считывать данные из одного. Для этого можно снова использовать File объект. Объект можно использовать для чтения каждой File строки по отдельности (разделенных разрывами строк) или для чтения отдельных элементов независимо от того, как они разделены.

В этой процедуре показано, как считывать и отображать данные, созданные в предыдущем примере.

  1. В корне веб-сайта создайте файл с именем DisplayData.cshtml.

  2. Замените существующее содержимое следующим образом:

    @{
        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".)

  3. Запустите страницу в браузере. Отображаются введенные данные для предыдущих примеров.

    Снимок экрана: окно браузера с данными из файла dot t x t, отображаемого в массиве.

Подсказка

Отображение данных из файла Microsoft Excel с разделителями-запятыми

Microsoft Excel можно использовать для сохранения данных, содержащихся в электронной таблице, в виде файла с разделителями-запятыми (.csv файла). При этом файл сохраняется в виде обычного текста, а не в формате Excel. Каждая строка в электронной таблице разделена разрывом строки в текстовом файле, а каждый элемент данных разделен запятыми. Код, показанный в предыдущем примере, можно использовать для чтения файла с разделителями-запятыми Excel, просто изменив имя файла данных в коде.

Удаление файлов

Чтобы удалить файлы с веб-сайта, можно использовать File.Delete. В этой процедуре показано, как разрешить пользователям удалять изображение (.jpg файл) из папки изображений , если они знают имя файла.

Замечание

Важно На рабочем веб-сайте обычно ограничивается, кто может вносить изменения в данные. Сведения о настройке членства и способах авторизации пользователей для выполнения задач на сайте см. в разделе "Добавление безопасности и членства" на сайт веб-страниц ASP.NET.

  1. На веб-сайте создайте вложенную папку с именем изображения.

  2. Скопируйте один или несколько .jpg файлов в папку изображений .

  3. В корне веб-сайта создайте файл с именем FileDelete.cshtml.

  4. Замените существующее содержимое следующим образом:

    @{
        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 методом), имя папки изображений , указанное пользователем, и ".jpg" в качестве литеральной строки.

    Чтобы удалить файл, код вызывает File.Delete метод, передав ему полный путь, который вы только что создали. В конце разметки код отображает сообщение подтверждения о том, что файл был удален.

  5. Запустите страницу в браузере.

    Снимок экрана: окно браузера с полем

  6. Введите имя файла для удаления и нажмите кнопку "Отправить". Если файл был удален, имя файла отображается в нижней части страницы.

Предоставление пользователям возможности отправки файла

Вспомогательный FileUpload элемент позволяет пользователям отправлять файлы на веб-сайт. В приведенной ниже процедуре показано, как разрешить пользователям отправлять один файл.

  1. Добавьте библиотеку веб-вспомогательных служб ASP.NET на веб-сайт, как описано в разделе "Установка вспомогательных служб" на сайте веб-страниц ASP.NET, если вы не добавили его ранее.

  2. В папке App_Data создайте папку и назовите ее UploadedFiles.

  3. В корневом каталоге создайте файл с именем FileUpload.cshtml.

  4. Замените существующее содержимое на странице следующим образом:

    @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 загруженного файла, чтобы на самом деле сохранить файл.

  5. Запустите страницу в браузере.

    Снимок экрана: страница веб-браузера

  6. Нажмите кнопку "Обзор" , а затем выберите файл для отправки.

    Снимок экрана: окно проводника с выбранным файлом и выделенным синим цветом, а кнопка

    Текстовое поле рядом с кнопкой "Обзор " будет содержать путь и расположение файла.

    Снимок экрана веб-страницы примера загрузки одного файла с выбранным файлом и кнопкой

  7. Нажмите кнопку Отправить.

  8. На веб-сайте щелкните правой кнопкой мыши папку проекта и нажмите кнопку "Обновить".

  9. Откройте папку UploadedFiles . Отправленный файл находится в папке.

    Снимок экрана: иерархия папок проекта, показывающая файл samples t x t, выделенный синим цветом в папке

Предоставление пользователям возможности загрузки нескольких файлов

В предыдущем примере пользователи могут отправлять один файл. Но вы можете использовать вспомогательный FileUpload элемент для отправки нескольких файлов за раз. Это удобно для сценариев, таких как отправка фотографий, где отправка одного файла за раз мучена. (Вы можете прочитать о отправке фотографий в разделе "Работа с изображениями" на сайте веб-страниц ASP.NET.) В этом примере показано, как разрешить пользователям отправлять два за раз, хотя вы можете использовать один и тот же метод для отправки больше, чем это.

  1. Добавьте библиотеку вспомогательных средств ASP.NET на ваш веб-сайт, как описано в разделе "Установка вспомогательных библиотек" на сайте веб-страниц ASP.NET, если вы еще не сделали этого.

  2. Создайте страницу с именем FileUploadMultiple.cshtml.

  3. Замените существующее содержимое на странице следующим образом:

    @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 суммирует все файлы, которые успешно отправлены и сохранены. Этот код учитывает возможность того, что ожидаемый файл может не загрузиться.

  4. Запустите страницу в браузере. В браузере отображается страница и два поля загрузки.

  5. Выберите два файла для отправки.

  6. Нажмите кнопку "Добавить другой файл". На странице отображается новое поле загрузки.

    Снимок экрана: страница веб-браузера

  7. Нажмите кнопку Отправить.

  8. На веб-сайте щелкните правой кнопкой мыши папку проекта и нажмите кнопку "Обновить".

  9. Откройте папку UploadedFiles , чтобы просмотреть успешно отправленные файлы.

Дополнительные ресурсы

Работа с изображениями на сайте веб-страниц ASP.NET

Экспорт в CSV-файл