问题描述
我正在开发一个带有按钮的应用程序,当单击该按钮时,它将调用Web api GET方法。此方法使用System.IO.Compression获取文件并创建一个zip文件夹。这部分效果很好。我看到它创建的文件夹,并且能够打开/解压缩该文件夹及其文件。我遇到的问题是,当文件返回到浏览器并且浏览器下载文件时,出现以下错误:“压缩(压缩)文件夹'... pathToTheDownloadedFile.zip'无效。我不明白我的意思做错了。所有其他非压缩文件都可以下载并正常打开。
这是我的网络API GET方法:
[HttpGet]
[Route("apI/OrderManager/ExtractAllDocuments/{orderNum}/{mappingId}/")]
public HttpResponseMessage ExtractAllDocuments(int orderNum,int mappingId)
{
try
{
var docPath = @"" + HttpContext.Current.Server.MapPath("MyPath");
var files = Directory.GetFiles(docPath);
string zipName = @"supportingdocuments_order" + orderNum + ".zip";
FileStream zipToOpen = new FileStream(docPath + zipName,FileMode.Create);
using (var zipArchive = new ZipArchive(zipToOpen,ZipArchiveMode.Create))
{
foreach (var fPath in files)
{
if (!fPath.Contains(".zip"))
{
zipArchive.CreateEntryFromFile(fPath,Path.GetFileName(fPath),CompressionLevel.Fastest);
}
}
}
zipToOpen.Close();
//At this point the directory is created and saved as it should be
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
var fullZipPath = docPath + zipName;
byte[] bytes = File.ReadAllBytes(fullZipPath);
response.Content = new ByteArrayContent(bytes);
response.Content.Headers.ContentLength = bytes.LongLength;
response.Content.Headers.Contentdisposition = new System.Net.Http.Headers.ContentdispositionHeaderValue("attachment");
response.Content.Headers.Contentdisposition.FileName = zipName;
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(MimeMapping.GetMimeMapping(zipName));
return response;
}
catch (Exception e)
{
var b = e.Message;
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.NotFound);
response.ReasonPhrase = string.Format("Failed To Extract Files");
throw new HttpResponseException(response);
}
}
这是我的$ .ajax电话:
$.ajax({
url: 'myApiUrl',method: 'GET'
}).done(function (data,status,xmlHeaderRequest) {
var downloadLink = document.createElement('a');
var blob = new Blob([data],{
type: xmlHeaderRequest.getResponseHeader('Content-Type')
});
var url = window.URL || window.webkitURL;
var downloadUrl = url.createObjectURL(blob);
var fileName = '';
// get the file name from the content disposition
var disposition = xmlHeaderRequest.getResponseHeader('Content-disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
fileName = matches[1].replace(/['"]/g,'');
}
}
// Blob download logic taken from: https://stackoverflow.com/questions/16086162/handle-file-download-from-ajax-post
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround for "HTML7007" and "Access Denied" error.
window.navigator.msSaveBlob(blob,fileName);
} else {
if (fileName) {
if (typeof downloadLink.download === 'undefined') {
window.location = downloadUrl;
} else {
downloadLink.href = downloadUrl;
downloadLink.download = fileName;
document.body.appendChild(downloadLink);
downloadLink.click();
}
} else {
window.location = downloadUrl;
}
setTimeout(function () {
url.revokeObjectURL(downloadUrl);
},100);
}
}).fail(function (data) {
$.notify({
// options
message:
'<i class="fas fa-exclamation-circle"></i> Could not download all documents.'
},{
// settings
type: 'danger',placement: {
from: "top",align: "left"
},delay: 2500,z_index: 10031
});
});
我对此完全不知所措。预先感谢您提供的任何帮助,我们将不胜感激。
解决方法
因此,在搜索之后,我找到了一个可行的解决方案。 $ .ajax不喜欢二进制数据,并且认为所有内容显然都是UTF-8文本编码。因此,我使用了XMLHttpRequest(xhr)。对于那些需要它的人,下面是c#和javascript解决方案的副本。
C#WebApi控制器:
public HttpResponseMessage ExtractAllDocuments(int orderNum,int mappingId)
{
try
{
var docPath = @"" + HttpContext.Current.Server.MapPath("myPath");
var files = Directory.GetFiles(docPath);
string zipName = @"Supporting-Documents-Order-" + orderNum + ".zip";
FileStream zipToOpen = new FileStream(docPath + zipName,FileMode.Create);
using (var zipArchive = new ZipArchive(zipToOpen,ZipArchiveMode.Create))
{
foreach (var fPath in files)
{
if (!fPath.Contains(".zip"))
{
zipArchive.CreateEntryFromFile(fPath,Path.GetFileName(fPath),CompressionLevel.Fastest);
}
}
}
zipToOpen.Close();
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(new FileStream(docPath + zipName,FileMode.Open,FileAccess.Read));
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = zipName;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
return response;
}
catch (Exception e)
{
var b = e.Message;
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.NotFound);
response.ReasonPhrase = string.Format("Failed To Extract Files");
throw new HttpResponseException(response);
}
}
前端JavaScript:
function extractAllDocuments() {
let xhr = new XMLHttpRequest();
xhr.addEventListener('readystatechange',function (e) {
if (xhr.readyState == 2 && xhr.status == 200) {
// Download is being started
}
else if (xhr.readyState == 3) {
// Download is under progress
}
else if (xhr.readyState == 4) {
//operation done
// Create a new Blob object using the response data of the onload object
var blob = new Blob([this.response],{ type: 'application/zip' });
//Create a link element,hide it,direct it towards the blob,and then 'click' it programatically
let a = document.createElement("a");
a.style = "display: none";
document.body.appendChild(a);
//Create a DOMString representing the blob and point the link element towards it
let url = window.URL.createObjectURL(blob);
a.href = url;
// get the file name from the content disposition
var fileName = '';
var disposition = xhr.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
fileName = matches[1].replace(/['"]/g,'');
}
}
a.download = fileName;
//programatically click the link to trigger the download
a.click();
//Remove From Server
$.ajax({
url: 'myUrl',method: 'DELETE'
}).done(function (data) {
}).fail(function (data) {
});
setTimeout(function () {
window.URL.revokeObjectURL(url);
},60 * 1000);
} else if (xhr.status == 400){
$.notify({
// options
message:
'<i class="fas fa-exclamation-circle"></i> Could not download all documents.'
},{
// settings
type: 'danger',placement: {
from: "top",align: "left"
},delay: 2500,z_index: 10031
});
}
});
//set the request type to post and the destination url to '/convert'
xhr.open('GET','MyUrl');
//set the reponse type to blob since that's what we're expecting back
xhr.responseType = 'blob';
xhr.send();
return false;
}