Завантаження файлів на ASP.net без використання сервера управління FileUpload


99

Як я можу отримати веб-форму ASP.net (v3.5) для публікації файлу за допомогою простої старої <input type="file" />?

Мені не цікаво використовувати керування сервером ASP.net FileUpload.

Відповіді:


133

У вашій аспіксі:

<form id="form1" runat="server" enctype="multipart/form-data">
 <input type="file" id="myFile" name="myFile" />
 <asp:Button runat="server" ID="btnUpload" OnClick="btnUploadClick" Text="Upload" />
</form>

У коді позаду:

protected void btnUploadClick(object sender, EventArgs e)
{
    HttpPostedFile file = Request.Files["myFile"];

    //check file was submitted
    if (file != null && file.ContentLength > 0)
    {
        string fname = Path.GetFileName(file.FileName);
        file.SaveAs(Server.MapPath(Path.Combine("~/App_Data/", fname)));
    }
}

3
@mathieu, шкода, що ви використовуєте варіант runat="server", він не є незалежним від серверних речей ASP.NET
Secret

що робити, якщо входів більше 1, і ви хочете, щоб окремі функції виконувались з обома наборами файлів.
Neville Nazerane

при використанні його для завантаження декількох файлів він повертає однакове ім'я файлу для всіх файлів і, таким чином, зберігає перший файл n кількість разів. Будь-яка ідея, як перебороти це?
sohaiby

@Martina Перевірте цей фрагмент коду для збереження декількох файлів
sohaiby

1
@DanielJ. Немає можливого способу не використовувати код-позаду, якщо ви збираєтеся робити щось із файлом згодом, тобто зберігати його в базі даних. Звичайно, ви можете використовувати прямий JavaScript, щоб захопити вхід і файл: var fileUploaded = document.getElementById("myFile").files[0];і ви навіть можете отримати байти за допомогою readAsArrayBuffer: stackoverflow.com/questions/37134433/… - але що ви збираєтеся робити з усіма цими байтами на стороні клієнта? ОП хоче взагалі уникнути зв'язку ASP .NET, а не на сервері. -1 тобі.
vapcguy

40

Ось рішення, не покладаючись на будь-яке управління на стороні сервера, подібно до того, як ОП описано у питанні.

HTML код на стороні клієнта:

<form action="upload.aspx" method="post" enctype="multipart/form-data">
    <input type="file" name="UploadedFile" />
</form>

Метод Page_Load upload.aspx:

if(Request.Files["UploadedFile"] != null)
{
    HttpPostedFile MyFile = Request.Files["UploadedFile"];
    //Setting location to upload files
    string TargetLocation = Server.MapPath("~/Files/");
    try
    {
        if (MyFile.ContentLength > 0)
        {
            //Determining file name. You can format it as you wish.
            string FileName = MyFile.FileName;
            //Determining file size.
            int FileSize = MyFile.ContentLength;
            //Creating a byte array corresponding to file size.
            byte[] FileByteArray = new byte[FileSize];
            //Posted file is being pushed into byte array.
            MyFile.InputStream.Read(FileByteArray, 0, FileSize);
            //Uploading properly formatted file to server.
            MyFile.SaveAs(TargetLocation + FileName);
        }
    }
    catch(Exception BlueScreen)
    {
        //Handle errors
    }
}

Слідкуйте за відправленням HTTPWebRequest виклику повного файлу в MyFile.FileName. Виклик WebClient просто надсилає ім'я файлу. HTTPWebRequest призведе до відмови MyFile.SaveAs. Лише витрачені години переслідували одного клієнта, який працює, а одного - не.
Боб Клегг

Я просто використовував Request.Files[0]замість Request.Files["UploadedFile"]і в той час як OP використовує прямий ASP .NET і не MVC, якщо хто -то хоче використовувати це для MVC, потрібно просто HttpPostedFileBaseзамість HttpPostedFile.
vapcguy

23

Вам доведеться встановити enctypeатрибут formдо multipart/form-data; то ви можете отримати доступ до завантаженого файлу за допомогою HttpRequest.Filesколекції.


Моя серверна форма знаходилася на головній сторінці, і я не міг додати дані з кількох частин / форм (з тих пір це було б на кожній сторінці). Швидкий і брудний спосіб вирішення проблеми полягав у тому, щоб додати прихований елемент управління завантаженням файлу. Потім WebForms автоматично додав багаточастинні / форми-дані. Мені довелося це зробити, тому що я використовував введення файлу з Angular2 і не міг використовувати серверне керування в шаблоні компонентів.
Джейсон

9

використовувати керування HTML з атрибутом сервера runat

 <input id="FileInput" runat="server" type="file" />

Потім в asp.net Codebehind

 FileInput.PostedFile.SaveAs("DestinationPath");

Також є кілька варіантів третьої партії , які покажуть прогрес, якщо вас зацікавить


3
Знову ж таки, це перетворює його на серверне управління. ;)
ahwm

@ahwm ОП хотів уникнути керування ASP .NET FileUpload ( <asp:FileUpload ID="fileUpload1" runat="server"></asp:FileUpload>) Це інакше, ніж казати не ставити поле runat=serverна inputполе.
vapcguy

1
Я вважаю, що вони не хочуть використовувати елементи керування ASP.NET. Що включає HtmlInputFileконтроль.
ahwm

8

Так, ви можете домогтися цього методом ajax post. на стороні сервера ви можете використовувати httphandler. Таким чином, ми не використовуємо ніяких елементів управління сервером відповідно до вашої вимоги.

за допомогою ajax ви також можете продемонструвати хід завантаження.

вам доведеться читати файл як вхідний потік.

using (FileStream fs = File.Create("D:\\_Workarea\\" + fileName))
    {
        Byte[] buffer = new Byte[32 * 1024];
        int read = context.Request.GetBufferlessInputStream().Read(buffer, 0, buffer.Length);
        while (read > 0)
        {
            fs.Write(buffer, 0, read);
            read = context.Request.GetBufferlessInputStream().Read(buffer, 0, buffer.Length);
        }
    } 

Зразок коду

function sendFile(file) {              
        debugger;
        $.ajax({
            url: 'handler/FileUploader.ashx?FileName=' + file.name, //server script to process data
            type: 'POST',
            xhr: function () {
                myXhr = $.ajaxSettings.xhr();
                if (myXhr.upload) {
                    myXhr.upload.addEventListener('progress', progressHandlingFunction, false);
                }
                return myXhr;
            },
            success: function (result) {                    
                //On success if you want to perform some tasks.
            },
            data: file,
            cache: false,
            contentType: false,
            processData: false
        });
        function progressHandlingFunction(e) {
            if (e.lengthComputable) {
                var s = parseInt((e.loaded / e.total) * 100);
                $("#progress" + currFile).text(s + "%");
                $("#progbarWidth" + currFile).width(s + "%");
                if (s == 100) {
                    triggerNextFileUpload();
                }
            }
        }
    }

2
Можливо, вам слід додати підказку, щоб додати, що fs.close()все інше може виявитись у нечитабельних файлах, оскільки вони залишаються якимось відкритими в IIS.
помилково

@mistapink Чи потік файлів не закритий, коли виконання виходить із використовуваного блоку?
Sebi

@Sebi, схоже, майже 3 роки тому цього не сталося. Давно не пробував цього, тому я не можу дати тут однозначної відповіді. Вибачте.
помилково

4

Колекція Request.Files містить будь-які файли, завантажені у вашу форму, незалежно від того, надходили вони з керування FileUpload або записані вручну <input type="file">.

Таким чином, ви можете просто написати звичайний старий тег для введення файлів у середині веб-форми, а потім прочитати файл, завантажений із колекції Request.Files.


4

Як відповіли інші, Request.Files - це HttpFileCollection, який містить усі опубліковані файли, вам потрібно лише запитати цей об’єкт для такого файлу:

Request.Files["myFile"]

Але що станеться, коли існує більше однієї вхідної позначки з однаковою назвою атрибута:

Select file 1 <input type="file" name="myFiles" />
Select file 2 <input type="file" name="myFiles" />

На стороні сервера попередній код Request.Files ["myFile"] повертає лише один об'єкт HttpPostedFile замість двох файлів. Я бачив у .net 4.5 метод розширення, який називається GetMultiple, але для переконливих версій він не існує, для цього я пропоную метод розширення як:

public static IEnumerable<HttpPostedFile> GetMultiple(this HttpFileCollection pCollection, string pName)
{
        for (int i = 0; i < pCollection.Count; i++)
        {
            if (pCollection.GetKey(i).Equals(pName))
            {
                yield return pCollection.Get(i);
            }
        }
}

Цей метод розширення поверне всі об'єкти HttpPostedFile, які мають назву "myFiles" в HttpFileCollection, якщо такі є.


2

HtmlInputFile управління

Я цим весь час користувався.


2
Для цього потрібно додати, runat="server"що по суті перетворює його на серверне управління, яке вони не хотіли використовувати.
ahwm

@ahwm Ні, ОП не хотів використовувати специфічне управління ASP .NET FileUpload. Це інакше, ніж сказати, що вони взагалі не хочуть використовувати серверне управління.
vapcguy


0
//create a folder in server (~/Uploads)
 //to upload
 File.Copy(@"D:\CORREO.txt", Server.MapPath("~/Uploads/CORREO.txt"));

 //to download
             Response.ContentType = ContentType;
             Response.AppendHeader("Content-Disposition", "attachment;filename=" + Path.GetFileName("~/Uploads/CORREO.txt"));
             Response.WriteFile("~/Uploads/CORREO.txt");
             Response.End();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.