首页 文章

我可以将Stream返回给用户并在服务器端生成数据时将其写入

提问于
浏览
-1

我有一个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 回答

  • 0

    我很确定你不能,因为当你使用下列之一时,文件只发送给用户:

    • HttpContext.Current.Response.End();

    • HttpContext.Current.Response.Flush();

    • HttpContext.Current.Response.Redirect("yourFile.zip");

    作为解决方法,您可以使用AJAX,以便用户在创建和下载文件时仍可以使用您的应用程序 .

    您也可以尝试以下代码:https://support.microsoft.com/en-us/kb/812406

相关问题