如何使用 C# 上传文件并将其保存到 Stream 以便进一步预览? [英] How can I upload a file and save it to a Stream for further preview using C#?
问题描述
有没有办法上传文件,保存到Stream,这个Stream我会暂时保存在Session中,最后,我会尝试预览这个Session中的这个上传文件??
Is there a way to upload a file, save it to a Stream, this Stream I will save it temporarily in a Session and, at last, I will try to preview this uploaded file that is in this Session??
例如,pdf 文件.
谢谢!!
已编辑
这是我想要做的:
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();
在另一种方法中,我正在这样做:
And in another method, I'm doing this:
byte[] imageByte = null;
imageByte = (byte[])Session["pdf"];
Response.ContentType = "application/pdf";
Response.Buffer = true;
Response.Clear();
Response.BinaryWrite(imageByte);
但是什么也没发生...我的浏览器甚至打开了一个 Nem 页面来显示 pdf 文件,但是显示一个窗口说该文件不是 pdf(或者类似文件不是以 pdf 启动的,我没有不明白)
But nothing happends... my browser even opens a nem page to show the pdf file, but a window is shown saying that the file is not a pdf (or something like the file doesn't initiate with pdf, I didn't understand that)
推荐答案
当然可以.我在我的 app 中将文件(PDF/图像)上传到我的数据库.我的模型对象实际上将文件存储为字节数组,但对于其他函数,我必须在流之间进行转换,因此我确定将其保持为流格式同样容易.
Sure is. I upload files (PDF/images) to my db in my app. My model object actually stores the file as a byte array but for other functions i have to convert to and from streams so im sure its just as easy to keep it in stream format.
以下是我的应用程序中的一些代码示例(复制粘贴)-
Here are some code examples (copy n paste) from my app-
我用来移动文件(PDF/图像)的 File
对象:
The File
object that i use to move files (PDFs / images) around:
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; }
}
...专用于 PDF 文件的 PdfDoc
类型:
..the PdfDoc
type specifically for PDF files:
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;
}
}
.. 接收文件上传的多部分 POST 的操作示例:
.. an example of an action that receives multi-part POST for file uploading:
//
// 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 });
}
现在您可以看到我在此处将文件对象传递给我的服务,但您可以选择将其添加到会话中并将 ID 传递回预览"视图.
Now you can see i pass the file object to my service here but you can choose to add it to the session and pass an id back to the 'preview' view for example.
最后,这是我用来将文件渲染到客户端的通用操作(您可以使用类似的方法从会话渲染文件/流):
Finally, here is a generic action i use to render files out to the client (you could have something similar render the files/stream from the 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);
}
我注意到我需要更多样本来解释上述内容-
I noticed i need more samples to explain the above-
对于上面的上传操作,FileUploadResultDTO
类:
For the upload action above, the FileUploadResultDTO
class:
public class FileUploadResultDTO
{
public List<File> Files { get; set; }
public Int32 TotalBytes { get; set; }
public string ErrorMessage { get; set; }
}
还有 GetFilesFromRequest
函数:
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;
}
最后(我希望我拥有你现在需要的一切)这个 ReadFully
函数.这不是我的设计.我是从网上得到的 - 流阅读可能很棘手.我发现这个函数是完全读取流的最成功的方法:
And finally (i hope i have everything you need now) this ReadFully
function. It's not my design. I got it from the net - stream reading can be tricky. I find this function is the most successful way to completely read a stream:
/// <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;
}
这篇关于如何使用 C# 上传文件并将其保存到 Stream 以便进一步预览?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!