4步学会用Aspose在ASP.NET中将文档合并为PDF

在各种业务环境中 , 将各种文档合并为一个PDF是客户最常问的问题之一 。 例如 , 假设您的组织有多个应用程序以XPS和PDF生成特定的文档 , 使用扫描的图像 , 并且您的用户希望将其中一些文档合并为一个PDF 。
本文演示了如何使用ASP.NET Core框架将多个文档合并到一个PDF中 。 Aspose.PDF提出了几种使用.NET合并PDF的方法 , 这些内容在本文中进行了介绍 。 在本文中 , 将讨论以下主题:

  • 如何使用ASP.NET Core Web API上传PDF或其他文档;
  • 如何实现简单的Web UI来选择要合并的PDF文件;
  • 如何实现用于合并PDF的简单Web API容器;
在本文中 , 我们将创建一个简单的ASP.NET Web API应用程序 , 该应用程序允许我们上载文档 , 选择2个或更多文件进行合并以及下载结果 。
4步学会用Aspose在ASP.NET中将文档合并为PDF文章插图
点击文末“了解更多”下载最新版Aspose.PDF
实施ASP.NET Core Web App以将各种文档合并为PDF步骤1:创建一个ASP.NET Core Web应用程序
我们将为此应用程序使用Web应用程序(模型-视图-控制器)模板 。
4步学会用Aspose在ASP.NET中将文档合并为PDF文章插图
创建基本应用程序后 , 我们将需要执行一些其他操作 。
  • 为.NET库添加Aspose.PDF作为依赖项(通过Nuget软件包管理器);
  • 添加resumable.js库;
  • 将临时文件和文档的wwwroot文件夹添加到该文件夹(例如files和temp);
  • 在appsettings.json中创建相应的属性 "Folders": { "Files": "files", "Temporary" : "temp" }
步骤2:实施Web API控制器以管理服务器上的文件
我们的控制器应执行以下操作:
  • 返回具有某些扩展名的文件列表(在本示例中 , 将仅显示.pdf , .jpg和.oxps文件);
  • 允许按文件名下载文件;
  • 允许通过文件名删除服务器上的文件;
using Aspose.Demo.Pdf.Merger.Models;using Microsoft.AspNetCore.Hosting;using Microsoft.AspNetCore.Mvc;using Microsoft.Extensions.Logging;using System.Collections.Generic;using System.IO;using System.Linq;using Microsoft.Extensions.Configuration;namespace Aspose.Demo.Pdf.Merger.Controllers{[Route("api/[controller]")][ApiController]public class FilesController : ControllerBase{private readonly Dictionary _contentType;private readonly ILogger _logger;private readonly string _storageRootFolder;public FilesController(ILogger logger,IWebHostEnvironment env,IConfiguration configuration){_logger = logger;_storageRootFolder = Path.Combine(env.WebRootPath, configuration["Folders:Files"]);_contentType = new Dictionary {{ ".txt", "text/plain"},{ ".pdf", "application/pdf"},{ ".doc", "application/vnd.ms-word"},{ ".docx", "application/vnd.ms-word"},{ ".xls", "application/vnd.ms-excel"},{ ".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},{ ".png", "image/png"},{ ".jpg", "image/jpeg"},{ ".jpeg", "image/jpeg"},{ ".gif", "image/gif"},{ ".csv", "text/csv"}};}// GET: /api/files[HttpGet]public IEnumerable GetFiles(){_logger.LogInformation($"Get files from {_storageRootFolder}");var files = new DirectoryInfo(_storageRootFolder).EnumerateFiles("*.pdf").ToList();files.AddRange(new DirectoryInfo(_storageRootFolder).EnumerateFiles("*.jpg"));files.AddRange(new DirectoryInfo(_storageRootFolder).EnumerateFiles("*.oxps"));//TODO: add other file types belowreturn files.Select(f => new FileViewModel { Name = f.Name, Size = f.Length });}[HttpGet("{id}")]public IActionResult OnGetFile(string id){_logger.LogInformation($"Get file {id}");var fileName = Path.Combine(_storageRootFolder, id);return File(System.IO.File.OpenRead(fileName), _contentType[Path.GetExtension(fileName)]);}[HttpDelete("{id}")]public IActionResult OnDeleteFile(string id){_logger.LogInformation($"Delete file {id}");var fileName = Path.Combine(_storageRootFolder, id);System.IO.File.Delete(fileName);return Ok();}}}然后将使用附加的库Resumable.JS来加载文件 , 因此将与加载文件相关的代码移至单独的控制器是有意义的 。
步骤3:实现Web API控制器以使用Resumable.JS上传文件
Resumable.JS库的主要功能是它允许您分块加载文件 。 因此 , 我们需要实现一些方法来处理此过程:
  • HTTP GET请求的方法 , 该方法应检查服务器上是否存在块;
  • HTTP POST请求的方法 , 该方法应该是服务器上的上传块;
  • 其他辅助方法(用于HTTP OPTIONS请求 , 合并块等)
using Microsoft.AspNetCore.Hosting;using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc;using Microsoft.Extensions.Logging;using System.IO;using Microsoft.Extensions.Configuration;namespace Aspose.Demo.Pdf.Merger.Controllers{[Route("api/[controller]")][ApiController]public class UploadController : ControllerBase{private readonly ILogger_logger;private readonly string _storageRootFolder;private readonly string _filesRootFolder;public UploadController(ILoggerlogger,IConfiguration configuration,IWebHostEnvironment env){_logger = logger;_storageRootFolder = Path.Combine(env.WebRootPath, configuration["Folders:Temporary"]);_filesRootFolder = Path.Combine(env.WebRootPath, configuration["Folders:Files"]);if (!Directory.Exists(_storageRootFolder))Directory.CreateDirectory(_storageRootFolder);}[HttpOptions]public object UploadFileOptions(){return Ok();}[HttpGet]public object Upload(int resumableChunkNumber, string resumableIdentifier){_logger.LogInformation($"Check if chunck {resumableChunkNumber} from {resumableIdentifier} is here.");return ChunkIsHere(resumableChunkNumber, resumableIdentifier) ? Ok() : StatusCode(418);}[HttpPost]public IActionResult Upload([FromQuery(Name = "ResumableIdentifier")] string resumableIdentifier,[FromQuery(Name = "ResumableFilename")] string resumableFilename,[FromQuery(Name = "ResumableChunkNumber")] int resumableChunkNumber,[FromQuery(Name = "ResumableTotalChunks")] int resumableTotalChunks,IFormFile file){_logger.LogInformation(file.FileName);var stream = System.IO.File.Create(GetChunkFileName(resumableChunkNumber, resumableIdentifier));file.CopyTo(stream);stream.Close();TryAssembleFile(resumableFilename, resumableIdentifier, resumableTotalChunks);return Ok();}#region Chunk methods[NonAction]private string GetChunkFileName(int chunkNumber, string identifier){return Path.Combine(_storageRootFolder, $"{identifier}_{chunkNumber}");}[NonAction]private string GetFilePath(string identifier){return Path.Combine(_storageRootFolder, identifier);}[NonAction]private bool ChunkIsHere(int chunkNumber, string identifier){return System.IO.File.Exists(GetChunkFileName(chunkNumber, identifier));}[NonAction]private bool AllChunksAreHere(string identifier, int chunks){for (var chunkNumber = 1; chunkNumber