【问题标题】:Generate Download link using asp.net core and angular使用 asp.net core 和 angular 生成下载链接
【发布时间】:2019-08-16 17:28:30
【问题描述】:

请帮我解决我的问题。

我正在创建一个网站,用户可以上传要转换为 pdf 的 word 文档。并且用户应该能够下载处理后的文件。

现在我有这个 Html 代码

<input type="file" (change)="upload($event.target.files)" />
    Upload Percent: {{percentDone}}% <br />

    <ng-container *ngIf="uploadSuccess">
      <button type="button">Download</button>
    </ng-container> 

这是 Angular 代码

upload(files: File[]){

    this.uploadAndProgress(files);
  }

uploadAndProgress(files: File[]){
    console.log(files)
    var formData = new FormData();
    Array.from(files).forEach(f => formData.append('file',f))

    this.http.post('http://localhost:5000/api/DocumentToPdf/Document', formData, {reportProgress: true, observe: 'events'})
      .subscribe(event => {
        if (event.type === HttpEventType.UploadProgress) {
          this.percentDone = Math.round(100 * event.loaded / event.total);
        } else if (event instanceof HttpResponse) {
          this.uploadSuccess = true;
        }
    });
  }

这是 Asp.net Core 代码

[Route("api/[controller]")]
[ApiController]
public class DocumentToPdfController : ControllerBase
{
    private readonly IDocumentToPdf _documentToPdf;

    public DocumentToPdfController(IDocumentToPdf documentToPdf)
    {
        _documentToPdf = documentToPdf;
    }    

    [HttpPost("Document")]
    public async Task<Stream> Document()
    {
        try
        {
            var file = Request.Form.Files;

            return  _documentToPdf.DocumentToPdf(file[0].OpenReadStream());
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            Console.WriteLine(ex.StackTrace);
            throw;
        }
    }
}

我能够处理上传的文件。

但问题是我没有下载输出文件的功能。

截至目前,Asp.net 核心的回归是 Stream。

我怎样才能调整它以能够下载文件过程?

如果我要编写在服务器端处理的文件。如何创建能够下载输出文件的下载链接?

更新:根据 sdev95 评论。我把我的代码改成了

控制器:

public HttpResponseMessage Document()
        {
            try
            {
                var file = Request.Form.Files;

                var fileData = _documentToPdf.DocumentToPdf(file[0].OpenReadStream());
                HttpResponseMessage response = null;


                response = new HttpResponseMessage
                {
                    StatusCode = HttpStatusCode.OK,
                    Content = new ByteArrayContent(fileData.ToArray())
                };
                response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
                response.Content.Headers.ContentDisposition.FileName = "pdf.pdf";
                response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                response.Content.Headers.ContentLength = fileData.Length;

                Console.WriteLine(fileData.Length);


                return response;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
                throw;
            }
        }

还有角码

upload(files: File[]){

    this.uploadAndProgress(files);
  }

  uploadAndProgress(files: File[]){
    console.log(files)
    var formData = new FormData();
    Array.from(files).forEach(f => formData.append('file',f))

    this.http.post('http://localhost:5000/api/DocumentToPdf/Document', formData, {reportProgress: true, responseType: 'blob',  observe: 'events'})
      .subscribe(event => {
        if (event.type === HttpEventType.UploadProgress) {
          this.percentDone = Math.round(100 * event.loaded / event.total);
        } else if (event instanceof HttpResponse) {
          this.uploadSuccess = true;
          console.log('Success');
          console.log('event: ' + event);
          this.downloadFile(event, 'download.pdf');
        }
    });
  }

  downloadFile(data: any, filename: string) {
    const blob = new Blob([data], { type: 'application/octet-stream' });
    saveAs(blob, filename);
  }

但我现在的问题是。它下载一个文件,但下载的文件只有1kb。

我调试了 asp.net 核心,代码 fileData.Length 返回类似于 49648 的内容,但为什么它只返回一个 1kb 的文件。我的代码有什么问题?

谢谢

【问题讨论】:

    标签: angular asp.net-core asp.net-web-api angular7 filesaver.js


    【解决方案1】:

    假设您从后端获取了正确的数据。你有几个选择。

    在客户端下载文件的几个库选项:

    如果您不想使用 3rd 方库,您可以尝试手动执行并从后端返回一个字节数组,那么下面的代码可以工作:)。

    示例中的结果是来自后端的响应。

    let file = new Blob([result.blob()], {type: 'application/pdf'});
    let fileUrl = URL.createObjectURL(file);
    var link = document.createElement('a');
    link.href = fileUrl;
    link.download = "filename___x.pdf";
    document.body.appendChild(link);
    link.click();
    

    【讨论】:

    • 所以我可以使用 Stream 或者我需要来自后端的文件。谢谢
    • 一种可能性是在后端将文件作为字节数组读取,并让后端将其返回到类似的内容: `` HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.Accepted); result.Content = new ByteArrayContent(BYTEARRAYFROMFILE); result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");返回结果; ```
    • 美好的一天。我能够根据您的评论更改代码。但是为什么它只下载一个 1kb 的文件呢?我更新了问题。请帮助我。谢谢
    • 你好@classname13,我不确定,我在工作代码中拥有的是 new MediaTypeHeaderValue("application/pdf") 而不是 octet-stream 和 Angular 代码中的相同。文件保护程序文件显示什么? fileData.ToArray() 是否返回 byteArray?您还可以在浏览器的网络选项卡中查看更多信息,并从那里进行调试:)。
    【解决方案2】:

    由于您的文件来自云端(服务器),我会尝试建议您使用服务器技术的东西

    您也可以尝试不使用文件保护程序或流保护程序。 如果您提交包含要转换的文档的表单并单击提交,那么您可以使用服务器通过将 content-disposition 标头附加到响应来保存文件,然后它将保存文件。 (当被 ajax 方法请求时,content-disposition 标头没有任何意义)

    如果文件不是通过文件输入选择的,那么你可以 创建表单,附加文件输入,将文件附加为FileList

    StreamSaver 尝试模拟服务器剂量,因此如果您可以直接使用服务器执行此操作,则无需包含 filesaver、streamsaver 或任何 ajax 内容

    【讨论】:

    • (我是 StreamSaver 的创建者,也是 FileSaver 的重要贡献者)
    猜你喜欢
    • 2017-10-29
    • 2012-08-05
    • 1970-01-01
    • 2021-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-14
    相关资源
    最近更新 更多