Mengupload File di ASP.net tanpa menggunakan kontrol server FileUpload

99

Bagaimana saya bisa mendapatkan formulir web ASP.net (v3.5) untuk mengirim file menggunakan format lama biasa <input type="file" />?

Saya tidak tertarik menggunakan kontrol server ASP.net FileUpload.

Ronnie Overby
sumber

Jawaban:

133

Di aspx Anda:

<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>

Dalam kode di belakang:

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)));
    }
}
mathieu
sumber
3
@mathieu, sayang sekali varian yang Anda gunakan runat="server", ini tidak terlepas dari hal-hal server ASP.NET
Rahasia
bagaimana jika ada lebih dari 1 masukan dan Anda ingin fungsi terpisah dijalankan dengan kedua kumpulan file.
Neville Nazerane
saat menggunakannya untuk mengunggah banyak file, ia mengembalikan nama file yang sama untuk semua file dan karenanya menyimpan file pertama n beberapa kali. Ada ide bagaimana mengatasinya?
sohaiby
@Martina Periksa cuplikan kode ini untuk menyimpan banyak file
sohaiby
1
@Bayu_joo Tidak ada cara yang mungkin untuk tidak menggunakan kode di belakang jika Anda akan melakukan sesuatu dengan file setelahnya, misalnya menyimpannya dalam database. Tentu, Anda bisa menggunakan JavaScript langsung untuk mengambil input & file: var fileUploaded = document.getElementById("myFile").files[0];dan Anda bahkan bisa mendapatkan byte menggunakan readAsArrayBuffer: stackoverflow.com/questions/37134433/… - tetapi apa yang akan Anda lakukan dengan semua byte di sisi klien? OP ingin menghindari komunikasi sisi server kontrol-bukan ASP .NET sama sekali. -1 untukmu.
vapcguy
40

Berikut adalah solusi tanpa bergantung pada kontrol sisi server apa pun, seperti yang dijelaskan OP dalam pertanyaan.

Kode HTML sisi klien:

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

Metode pemuatan halaman dari 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
    }
}
Aycan Yaşıt
sumber
Hati-hati dengan panggilan HTTPWebRequest yang mengirimkan jalur file lengkap di MyFile.FileName. Panggilan WebClient hanya mengirimkan nama file. HTTPWebRequest akan menyebabkan MyFile.SaveAs gagal. Hanya membuang waktu berjam-jam mengejar satu klien yang bekerja dan satu klien tidak.
Bob Clegg
Saya hanya menggunakan Request.Files[0]alih-alih Request.Files["UploadedFile"]dan sementara OP menggunakan ASP .NET langsung dan bukan MVC, jika ada yang ingin menggunakan ini untuk MVC, Anda hanya perluHttpPostedFileBase bukan HttpPostedFile.
vapcguy
23

Anda harus menyetel enctypeatribut formke multipart/form-data; kemudian Anda dapat mengakses file yang diunggah menggunakan HttpRequest.Fileskoleksi.

csgero
sumber
Formulir server saya berada di halaman master dan saya tidak dapat menambahkan multipart / form-data (sejak itu akan ada di setiap halaman). Solusi cepat dan kotor adalah menambahkan kontrol FileUpload tersembunyi ke halaman. WebForms kemudian menambahkan multipart / form-data secara otomatis. Saya harus melakukan ini karena saya menggunakan input file dengan Angular2 dan tidak dapat menggunakan kontrol server di template komponen.
Jason
9

gunakan kontrol HTML dengan atribut server runat

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

Kemudian di asp.net Codebehind

 FileInput.PostedFile.SaveAs("DestinationPath");

Ada juga beberapa opsi pihak ke-3 yang akan menunjukkan kemajuan jika Anda tertarik

cgreeno.dll
sumber
3
Sekali lagi, itu mengubahnya menjadi kontrol server. ;)
ahwm
@ahwm OP ingin menghindari ASP .NET FileUpload control ( <asp:FileUpload ID="fileUpload1" runat="server"></asp:FileUpload>) Itu berbeda dengan mengatakan untuk tidak meletakkan runat=serverdi inputlapangan.
vapcguy
1
Saya menganggap itu berarti mereka tidak ingin menggunakan kontrol ASP.NET. Yang termasuk HtmlInputFilekontrol.
ahwm
8

Ya, Anda dapat mencapai ini dengan metode posting ajax. di sisi server Anda dapat menggunakan httphandler. Jadi kami tidak menggunakan kontrol server apa pun sesuai kebutuhan Anda.

dengan ajax Anda juga dapat menunjukkan kemajuan unggahan.

Anda harus membaca file tersebut sebagai inputstream.

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);
        }
    } 

Kode sampel

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();
                }
            }
        }
    }
Samuel Joy
sumber
2
Mungkin Anda harus menambahkan petunjuk untuk menambahkan fs.close()semua yang lain mungkin berakhir di file yang tidak dapat dibaca karena mereka tetap terbuka dalam IIS.
mistapink
@mistapink Apakah aliran file tidak ditutup ketika eksekusi meninggalkan blok using?
Sebi
@Sebi sepertinya hampir 3 tahun yang lalu tidak. Lama tidak mencobanya, jadi saya tidak bisa memberikan jawaban yang pasti di sini. Saya menyesal.
mistapink
4

Koleksi Request.Files berisi semua file yang diunggah dengan formulir Anda, terlepas dari apakah itu berasal dari kontrol FileUpload atau ditulis secara manual <input type="file">.

Jadi Anda bisa menulis tag input file lama biasa di tengah WebForm Anda, dan kemudian membaca file yang diunggah dari koleksi Request.Files.

David
sumber
4

Karena orang lain memiliki jawaban, Request.Files adalah HttpFileCollection yang berisi semua file yang telah diposting, Anda hanya perlu menanyakan objek itu untuk file seperti ini:

Request.Files["myFile"]

Tetapi apa yang terjadi jika ada lebih dari satu mark-up input dengan nama atribut yang sama:

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

Di sisi server, kode sebelumnya Request.Files ["myFile"] hanya mengembalikan satu objek HttpPostedFile alih-alih dua file. Saya telah melihat di .net 4.5 metode ekstensi yang disebut GetMultiple tetapi untuk versi sebelumnya tidak ada, dalam hal ini saya mengusulkan metode ekstensi sebagai:

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);
            }
        }
}

Metode ekstensi ini akan mengembalikan semua objek HttpPostedFile yang memiliki nama "myFiles" di HttpFileCollection jika ada.

Joey O
sumber
2

Kontrol HtmlInputFile

Saya telah menggunakan ini sepanjang waktu.

Lurker Memang
sumber
2
Itu membutuhkan penambahan runat="server"yang pada dasarnya mengubahnya menjadi kontrol server, yang tidak ingin mereka gunakan.
ahwm
@ahwm Tidak, OP tidak ingin menggunakan kontrol ASP .NET FileUpload tertentu. Itu berbeda dengan mengatakan mereka tidak ingin menggunakan kontrol sisi server, secara umum.
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();
Jean Pierre Yenque
sumber