2009-10-31 30 views
12

Có cách nào để tải tệp lên, lưu tệp vào Luồng, Luồng này tôi sẽ lưu tạm thời trong Phiên và cuối cùng, tôi sẽ thử xem trước tệp được tải lên này trong Phiên này không ??Làm cách nào để tải lên tệp và lưu tệp đó vào Luồng để xem trước thêm bằng C#?

Ví dụ: tệp pdf.

Cảm ơn !!

EDITED

Dưới đây là những gì tôi đang cố gắng để làm:

HttpPostedFileBase hpf = Request.Files[0] as HttpPostedFileBase; 
byte[] buffer = new byte[hpf.InputStream.Length]; 
MemoryStream ms = new MemoryStream(buffer); 
ms.Read(buffer, 0, (int)ms.Length); 
Session["pdf"] = ms.ToArray(); 
ms.Close(); 

Và trong phương pháp khác, tôi đang làm điều này:

byte[] imageByte = null; 

imageByte = (byte[])Session["pdf"]; 

Response.ContentType = "application/pdf"; 
Response.Buffer = true; 
Response.Clear(); 
Response.BinaryWrite(imageByte); 

Nhưng không có gì happends .. Trình duyệt của tôi thậm chí còn mở một trang nem để hiển thị tập tin pdf, nhưng một cửa sổ được hiển thị nói rằng tập tin không phải là một pdf (hoặc một cái gì đó giống như các tập tin không bắt đầu với pdf, tôi không hiểu điều đó)

+0

Tham khảo ví dụ của tôi dưới đây mà viết byte mảng như một FileResult. Nó an toàn hơn Response.BinaryWrite vì bạn đang sử dụng mvc aspnet. Ngoài ra, hãy sử dụng trình đọc luồng tốt hơn (xem bản chỉnh sửa của tôi bên dưới) và duyệt qua mã của bạn để xác minh rằng tệp đã tải lên thực sự bị bán phá giá trong phiên. ;) –

+1

Vấn đề chính với mã của bạn là bạn chưa bao giờ đọc từ luồng đầu vào. Bạn đang tạo một bộ đệm với kích thước phù hợp, nhưng bạn đọc từ luồng bộ nhớ trống vào bộ đệm thay vì từ luồng đầu vào. Những gì bạn nhận được chỉ là một mảng đầy đủ các số không, mà rõ ràng là không hoạt động như một tập tin PDF. – Guffa

Trả lời

15

Chắc chắn là. Tôi tải tệp (PDF/hình ảnh) lên db của tôi trong app. Đối tượng mô hình của tôi thực sự lưu trữ các tập tin như là một mảng byte, nhưng đối với các chức năng khác tôi phải chuyển đổi sang và từ các dòng để im chắc chắn nó chỉ là dễ dàng để giữ nó trong định dạng dòng.

Dưới đây là một số ví dụ mã (copy n paste) từ cấp ứng dụng

Đối tượng File của tôi mà tôi sử dụng để di chuyển các file (PDF/images) xung quanh:

public class File : CustomValidation, IModelBusinessObject 
{ 
    public int ID { get; set; } 
    public string MimeType { get; set; } 
    public byte[] Data { get; set; } 
    public int Length { get; set; } 
    public string MD5Hash { get; set; } 
    public string UploadFileName { get; set; } 
} 

..the PdfDoc loại đặc biệt cho các tập tin PDF:

public class PdfDoc : File 
{ 
    public int ID { get; set; } 
    public int FileID 
    { 
     get { return base.ID; } 
     set { base.ID = value; } 
    } 
    [StringLength(200, ErrorMessage = "The Link Text must not be longer than 200 characters")] 
    public string LinkText { get; set; } 


    public PdfDoc() { } 

    public PdfDoc(File file) 
    { 
     MimeType = file.MimeType; 
     Data = file.Data; 
     Length = file.Length; 
     MD5Hash = file.MD5Hash; 
     UploadFileName = file.UploadFileName; 
    } 

    public PdfDoc(File file, string linkText) 
    { 
     MimeType = file.MimeType; 
     Data = file.Data; 
     Length = file.Length; 
     MD5Hash = file.MD5Hash; 
     UploadFileName = file.UploadFileName; 

     LinkText = linkText; 
    } 
} 

.. ví dụ về một hành động tiếp nhận đa phần POST cho tập tin tải lên:

// 
    // POST: /Announcements/UploadPdfToAnnouncement/ID 
    [KsisAuthorize(Roles = "Admin, Announcements")] 
    [AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult UploadPdfToAnnouncement(int ID) 
    { 
     FileManagerController.FileUploadResultDTO files = 
      FileManagerController.GetFilesFromRequest((HttpContextWrapper)HttpContext); 
     if (String.IsNullOrEmpty(files.ErrorMessage) && files.TotalBytes > 0) 
     { 
      // add SINGLE file to the announcement 
      try 
      { 
       this._svc.AddAnnouncementPdfDoc(
        this._svc.GetAnnouncementByID(ID), 
        new PdfDoc(files.Files[0]), 
        new User() { UserName = User.Identity.Name }); 
      } 
      catch (ServiceExceptions.KsisServiceException ex) 
      { 
       // only handle our exceptions 
       base.AddErrorMessageLine(ex.Message); 
      } 
     } 

     // redirect back to detail page 
     return RedirectToAction("Detail", "Announcements", new { id = ID }); 
    } 

Bây giờ bạn có thể thấy tôi vượt qua các đối tượng tập tin để dịch vụ của tôi ở đây nhưng bạn có thể chọn để thêm nó vào phiên và vượt qua một id trở lại quan điểm 'xem trước' chẳng hạn.

Cuối cùng, đây là một hành động chung tôi sử dụng để render file ra cho khách hàng (bạn có thể có một cái gì đó tương tự như làm cho các tập tin/suối từ Session):

// 
    // GET: /FileManager/GetFile/ID 
    [OutputCache(Order = 2, Duration = 600, VaryByParam = "ID")] 
    public ActionResult GetFile(int ID) 
    { 
     FileService svc = ObjectFactory.GetInstance<FileService>(); 

     KsisOnline.Data.File result = svc.GetFileByID(ID); 

     return File(result.Data, result.MimeType, result.UploadFileName); 
    } 

EDIT:
tôi nhận thấy tôi cần thêm mẫu để giải thích sự above-

Đối với hành động tải lên trên, lớp FileUploadResultDTO:

public class FileUploadResultDTO 
    { 
     public List<File> Files { get; set; } 
     public Int32 TotalBytes { get; set; } 
     public string ErrorMessage { get; set; } 
    } 

GetFilesFromRequest chức năng:

public static FileUploadResultDTO GetFilesFromRequest(HttpContextWrapper contextWrapper) 
    { 
     FileUploadResultDTO result = new FileUploadResultDTO(); 
     result.Files = new List<File>(); 

     foreach (string file in contextWrapper.Request.Files) 
     { 
      HttpPostedFileBase hpf = contextWrapper.Request.Files[file] as HttpPostedFileBase; 
      if (hpf.ContentLength > 0) 
      { 
       File tempFile = new File() 
       { 
        UploadFileName = Regex.Match(hpf.FileName, @"(/|\\)?(?<fileName>[^(/|\\)]+)$").Groups["fileName"].ToString(), // to trim off whole path from browsers like IE 
        MimeType = hpf.ContentType, 
        Data = FileService.ReadFully(hpf.InputStream, 0), 
        Length = (int)hpf.InputStream.Length 
       }; 
       result.Files.Add(tempFile); 
       result.TotalBytes += tempFile.Length; 
      } 
     } 

     return result; 
    } 

Và cuối cùng (tôi hy vọng tôi có mọi thứ bạn cần bây giờ) ReadFully chức năng này. Nó không phải là thiết kế của tôi. Tôi nhận được nó từ đọc net - dòng có thể được khôn lanh.Tôi thấy chức năng này là cách thành công nhất để đọc toàn bộ luồng:

/// <summary> 
    /// Reads data from a stream until the end is reached. The 
    /// data is returned as a byte array. An IOException is 
    /// thrown if any of the underlying IO calls fail. 
    /// </summary> 
    /// <param name="stream">The stream to read data from</param> 
    /// <param name="initialLength">The initial buffer length</param> 
    public static byte[] ReadFully(System.IO.Stream stream, long initialLength) 
    { 
     // reset pointer just in case 
     stream.Seek(0, System.IO.SeekOrigin.Begin); 

     // If we've been passed an unhelpful initial length, just 
     // use 32K. 
     if (initialLength < 1) 
     { 
      initialLength = 32768; 
     } 

     byte[] buffer = new byte[initialLength]; 
     int read = 0; 

     int chunk; 
     while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0) 
     { 
      read += chunk; 

      // If we've reached the end of our buffer, check to see if there's 
      // any more information 
      if (read == buffer.Length) 
      { 
       int nextByte = stream.ReadByte(); 

       // End of stream? If so, we're done 
       if (nextByte == -1) 
       { 
        return buffer; 
       } 

       // Nope. Resize the buffer, put in the byte we've just 
       // read, and continue 
       byte[] newBuffer = new byte[buffer.Length * 2]; 
       Array.Copy(buffer, newBuffer, buffer.Length); 
       newBuffer[read] = (byte)nextByte; 
       buffer = newBuffer; 
       read++; 
      } 
     } 
     // Buffer is now too big. Shrink it. 
     byte[] ret = new byte[read]; 
     Array.Copy(buffer, ret, read); 
     return ret; 
    } 
+0

Tôi đã chỉnh sửa câu hỏi của mình! Hãy xem! :-) – AndreMiranda

+0

Thaaaaaanks rất nhiều cottsak! Nó đã làm việc!! :-) Và tôi cũng đã thay đổi thành một tập tin kết quả, để được nhiều MVC! -) – AndreMiranda

+0

@AndreMiranda: hi 5 ;-) –

2

Có, nhưng bạn không thể lưu nó vào luồng. Luồng không chứa bất kỳ dữ liệu nào, nó chỉ là phương tiện để truy cập bộ nhớ thực.

Lấy dữ liệu dưới dạng mảng byte, sau đó bạn có thể đặt dữ liệu vào biến phiên, lưu dưới dạng tệp và gửi dưới dạng phản hồi.

Sử dụng một BinaryReader để lấy dữ liệu từ các dòng đầu vào cho một mảng byte:

byte[] data; 
using (BinaryReader reader = new BinaryReader(uploadedFile.InputStream)) { 
    data = reader.ReadBytes((int) uploadedFile.InputStream.Length); 
} 

(Chỉnh sửa: Thay đổi của một StreamReader để một BinaryReader)

+0

data = reader.ReadToEnd() sẽ không hoạt động vì ReadToEnd() trả về một chuỗi – AndreMiranda

+0

@AndreMiranda: tham khảo chỉnh sửa của tôi ở trên. đọc luồng có thể phức tạp –

+0

@AndreMiranda: Vâng, bạn nói đúng. Chỉ cần sử dụng một BinaryReader thay vì một StreamReader. Xem chỉnh sửa của tôi ở trên. – Guffa

Các vấn đề liên quan