การอัปโหลดไฟล์ใน ASP.net โดยไม่ใช้ตัวควบคุมเซิร์ฟเวอร์ FileUpload


99

ฉันจะรับเว็บฟอร์ม ASP.net (v3.5) เพื่อโพสต์ไฟล์โดยใช้แบบเก่าธรรมดาได้<input type="file" />อย่างไร

ฉันไม่สนใจที่จะใช้การควบคุมเซิร์ฟเวอร์ ASP.net FileUpload

คำตอบ:


133

ใน aspx ของคุณ:

<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
ความลับ

จะเกิดอะไรขึ้นถ้ามีอินพุตมากกว่า 1 รายการและคุณต้องการให้ฟังก์ชันแยกจากกันทำงานกับไฟล์ทั้งสองชุด
Neville Nazerane

ในขณะที่ใช้เพื่ออัปโหลดไฟล์หลายไฟล์จะส่งคืนชื่อไฟล์เดียวกันสำหรับไฟล์ทั้งหมดและด้วยเหตุนี้จึงบันทึกไฟล์แรก n จำนวนครั้ง มีความคิดอย่างไรที่จะเอาชนะมัน?
sohaiby

@Martina ตรวจสอบข้อมูลโค้ดนี้เพื่อบันทึกไฟล์หลายไฟล์
sohaiby

1
@DanielJ. ไม่มีทางเป็นไปได้ที่จะไม่ใช้โค้ดข้างหลังหากคุณกำลังจะทำอะไรกับไฟล์ในภายหลังนั่นคือการจัดเก็บไว้ในฐานข้อมูล แน่นอนว่าคุณสามารถใช้ JavaScript แบบตรงเพื่อคว้าอินพุต & ไฟล์: var fileUploaded = document.getElementById("myFile").files[0];และคุณยังสามารถรับไบต์โดยใช้readAsArrayBuffer: stackoverflow.com/questions/37134433/… - แต่คุณจะทำอย่างไรกับไบต์ฝั่งไคลเอ็นต์ทั้งหมด? OP ต้องการหลีกเลี่ยงการสื่อสารแบบควบคุม ASP .NET ไม่ใช่ฝั่งเซิร์ฟเวอร์โดยสิ้นเชิง -1 ถึงคุณ
vapcguy

40

นี่คือวิธีแก้ปัญหาโดยไม่ต้องอาศัยการควบคุมฝั่งเซิร์ฟเวอร์เช่นเดียวกับที่ OP ได้อธิบายไว้ในคำถาม

โค้ด 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 ล้มเหลว เสียเวลาไปกับการไล่ลูกค้าคนหนึ่งที่ทำงานและไม่มีลูกค้าอีก
Bob Clegg

ฉันเพิ่งใช้Request.Files[0]แทนRequest.Files["UploadedFile"]และในขณะที่ OP ใช้ ASP .NET แบบตรงไม่ใช่ MVC หากใครต้องการใช้สิ่งนี้สำหรับ MVC คุณก็ต้องHttpPostedFileBaseใช้แทนHttpPostedFile.
vapcguy

23

คุณจะต้องตั้งค่าenctypeแอตทริบิวต์ของformto multipart/form-data; จากนั้นคุณสามารถเข้าถึงไฟล์ที่อัปโหลดโดยใช้HttpRequest.Filesคอลเล็กชัน


ฟอร์มเซิร์ฟเวอร์ของฉันอยู่ในหน้าต้นแบบและฉันไม่สามารถเพิ่มข้อมูลหลายส่วน / ฟอร์มได้ (ตั้งแต่นั้นมาจะอยู่ในทุกหน้า) วิธีแก้ปัญหาที่รวดเร็วและสกปรกคือการเพิ่มตัวควบคุม FileUpload ที่ซ่อนอยู่ในเพจ จากนั้น WebForms จะเพิ่มข้อมูลหลายส่วน / แบบฟอร์มโดยอัตโนมัติ ฉันต้องทำสิ่งนี้เพราะฉันใช้อินพุตไฟล์กับ Angular2 และไม่สามารถใช้การควบคุมเซิร์ฟเวอร์ในเทมเพลตคอมโพเนนต์ได้
Jason

9

ใช้การควบคุม HTML กับแอ็ตทริบิวต์เซิร์ฟเวอร์ runat

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

จากนั้นใน asp.net Codebehind

 FileInput.PostedFile.SaveAs("DestinationPath");

นอกจากนี้ยังมีตัวเลือกของบุคคลที่ 3ที่จะแสดงความคืบหน้าหากคุณบุกรุก


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 ในฝั่งเซิร์ฟเวอร์คุณสามารถใช้ 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

@mistapink สตรีมไฟล์ไม่ถูกปิดเมื่อการดำเนินการออกจากบล็อกการใช้งานหรือไม่
Sebi

@ Sebi ดูเหมือนว่าเกือบ 3 ปีที่แล้วมันไม่ได้ ไม่ได้ลองมาเป็นเวลานานดังนั้นฉันไม่สามารถให้คำตอบที่ชัดเจนได้ที่นี่ ฉันขอโทษ.
mistapink

4

คอลเลกชัน Request.Files มีไฟล์ที่อัปโหลดด้วยแบบฟอร์มของคุณไม่ว่าไฟล์เหล่านั้นจะมาจากตัวควบคุม FileUpload หรือเขียนด้วยตนเอง<input type="file">ก็ตาม

ดังนั้นคุณสามารถเขียนแท็กอินพุตไฟล์เก่า ๆ ที่อยู่ตรงกลางของ WebForm ของคุณจากนั้นอ่านไฟล์ที่อัปโหลดจากคอลเลกชัน 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 ไม่ OP ไม่ต้องการใช้ตัวควบคุม 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();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.