我有一个WCF Web服务,可以构建项目并允许它们通过Web界面下载 .
如果在服务压缩文件夹之前从未下载过构建并返回zip文件,如果在zip文件已经存在之前已经下载并且可以下载而无需等待它压缩 .
由于zip进程对于某些构建来说可能非常耗时,因此我希望能够在发出请求后立即将Stream返回给用户,并在生成时开始将zip文件数据写入其中 . (在我看来,用户更友好)这样的事情会有可能吗?
注意:我目前正在使用System.IO.Compression进行压缩,但是我可以使用像dotnetzip这样的其他库,如果这样可以使任务变得更容易/可能 .
我目前的代码在这里:
public Stream DownloadBuildOutput(string BuildID)
{
noCaching();
int Buildid;
string InputFolder = null ;
string OutputName;
string OutputPath;
if (Int32.TryParse(BuildID, out Buildid))
{
InputFolder = DatabaseManager.GetBuildLocation(Buildid);
}
else
{
throw new WebFaultException<string>("Argument for DownloadBuildOutput must be an Integer.", HttpStatusCode.BadRequest);
}
if (InputFolder != null)
{
OutputName = InputFolder.Substring(InputFolder.LastIndexOf('\\') + 1) + ".zip";
OutputPath = System.Configuration.ConfigurationManager.AppSettings["Workingfolder"] + "\\" + OutputName;
WebOperationContext.Current.OutgoingResponse.Headers.Set("content-disposition", "attachment;filename=" + OutputName);
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin: *");
if (new FileInfo(OutputPath).Exists)
{
FileStream exists = File.OpenRead(OutputPath);
return exists;
}
ZipFile.CreateFromDirectory(InputFolder, OutputPath);
}
else
{
throw new WebFaultException<string>("Could not find Build Location. Make sure the build exists and finished successfully.", HttpStatusCode.BadRequest);
}
return File.OpenRead(OutputPath);
}
编辑:使用Peter Duniho的评论我进一步说,我创建了一个ZipArchive,并在我的工作线程返回流时启动了一个新线程来向其写入信息:
output = File.Open(OutputPath,FileMode.OpenOrCreate, FileAccess.ReadWrite);
ZipArchive archive = new ZipArchive(output, ZipArchiveMode.Create, true);
DirectoryInfo dirinfo = new DirectoryInfo(InputFolder);
new ZipThread(dirinfo, archive, output);
return output;
我的zipthread类看起来像这样:public class ZipThread {private FileSystemInfo fileSystem;私人ZipArchive ziparchive;私有流;
public ZipThread(DirectoryInfo folder, ZipArchive archive, Stream stream)
{
this.ziparchive = archive ;
this.fileSystem = folder;
this.stream = stream ;
ThreadStart threadstart = new ThreadStart(CreateArchive);
Thread thread = new Thread(threadstart) ;
thread.IsBackground = true ;
thread.Start();
}
public void CreateArchive()
{
WriteZipFileFromDir(ziparchive, fileSystem);
stream.Close() ;
stream.Dispose() ;
}
private void WriteZipFileFromDir(ZipArchive archive, FileSystemInfo fileSystemInfo)
{
var directoryInfo = fileSystemInfo as DirectoryInfo;
if (directoryInfo != null)
{
foreach (var childInfo in directoryInfo.GetFileSystemInfos())
{
WriteZipFileFromDir(archive, childInfo);
}
}
if ( fileSystemInfo is FileInfo )
{
string entryname = fileSystemInfo.FullName.Substring((System.Configuration.ConfigurationManager.AppSettings["Workingfolder"] + "\\").Length) ;
archive.CreateEntryFromFile(fileSystemInfo.FullName, entryname);
}
}
}
我现在在 archive.CreateEntryFromFile(fileSystemInfo.FullName, entryname);
行获得一个System.ArgumentException "Stream was not writable"
1 回答
我很确定你不能,因为当你使用下列之一时,文件只发送给用户:
HttpContext.Current.Response.End();
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.Redirect("yourFile.zip");
作为解决方法,您可以使用AJAX,以便用户在创建和下载文件时仍可以使用您的应用程序 .
您也可以尝试以下代码:https://support.microsoft.com/en-us/kb/812406