ASP.NET (C#) Example

Caution

For server security, please refer to the link below when handling this work.

[Software Security Weakness Diagnosis Guide]

1. Image / Video / File Upload

Caution

The file-upload portion of the sample code below is intentionally minimal and lacks proper security handling.

For the file-upload portion, use what is already in place inside your project, and refer to the code below for the integration portion only.

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;

// Absolute path to WEB ROOT
private const string WEB_ROOT_ABS_PATH = @"C:\workspace\SynapEditor_C#\SynapEditor\wwwroot";

// Where uploaded files go
private readonly string UPLOAD_DIR_ABS_PATH = Path.Combine(WEB_ROOT_ABS_PATH, "uploads");

[HttpPost("api/uploadFile")]
public IActionResult UploadFile(IFormFile file)
{
    string uploadFileAbsPath = SaveFileToDisk(file).Result;
    string uploadFileRelPath = Path.GetRelativePath(UPLOAD_DIR_ABS_PATH, uploadFileAbsPath);
    return Ok(new { uploadPath = uploadFileRelPath });
}

private async Task<string> SaveFileToDisk(IFormFile file)
{
    string extension         = Path.GetExtension(file.FileName);
    string uploadFileName    = $"{Guid.NewGuid()}{extension}";
    string uploadFileAbsPath = Path.Combine(UPLOAD_DIR_ABS_PATH, uploadFileName);

    using (var fileStream = new FileStream(uploadFileAbsPath, FileMode.Create))
    {
        await file.CopyToAsync(fileStream);
    }
    return uploadFileAbsPath;
}

2. HWP / Word / Excel Document Import

Caution

The file-upload portion of the sample code below is intentionally minimal and lacks proper security handling.

For the file-upload portion, use what is already in place inside your project, and refer to the code below for the integration portion only.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;

private const string WEB_ROOT_ABS_PATH = @"C:\workspace\SynapEditor_C#\SynapEditor\wwwroot";

// Temporary workspace for decompressing converted documents
private readonly string WORK_DIR_ABS_PATH   = Path.Combine(WEB_ROOT_ABS_PATH, "works");
private readonly string UPLOAD_DIR_ABS_PATH = Path.Combine(WEB_ROOT_ABS_PATH, "uploads");

[HttpPost("api/importDoc")]
public async Task<IActionResult> ImportDoc(IFormFile file)
{
    // 1. Save the document to disk
    string uploadFileAbsPath = SaveFileToDisk(file).Result;

    // 2. Convert it to model data
    string importAbsPath = ExecuteConverter(uploadFileAbsPath).Result;
    string importRelPath = Path.GetRelativePath(WEB_ROOT_ABS_PATH, importAbsPath);

    // 3. Read the model data
    // From v2.3.0 the filename is "document.pb" (was "document.word.pb")
    string pbFileAbsPath = Path.Combine(importAbsPath, "document.pb");
    int[] serializedData = ReadPbData(pbFileAbsPath);

    // 4. Return
    return Ok(new { serializedData, importPath = importRelPath });
}

private async Task<string> SaveFileToDisk(IFormFile file)
{
    string extension         = Path.GetExtension(file.FileName);
    string uploadFileName    = $"{Guid.NewGuid()}{extension}";
    string uploadFileAbsPath = Path.Combine(UPLOAD_DIR_ABS_PATH, uploadFileName);

    using (var fileStream = new FileStream(uploadFileAbsPath, FileMode.Create))
    {
        await file.CopyToAsync(fileStream);
    }
    return uploadFileAbsPath;
}

private async Task<string> ExecuteConverter(string docFileAbsPath)
{
    const string CONVERTER_ABS_PATH  = @"C:\workspace\SynapEditor_C#\sedocConverter.exe";
    const string FONTS_DIR_ABS_PATH  = @"C:\workspace\SynapEditor_C#\fonts";
    const string TEMP_DIR_ABS_PATH   = @"C:\workspace\SynapEditor_C#\tmp";

    string outputAbsPath = Path.Combine(WORK_DIR_ABS_PATH, Path.GetFileName(docFileAbsPath));

    var startInfo = new ProcessStartInfo
    {
        FileName        = CONVERTER_ABS_PATH,
        Arguments       = $"-f {FONTS_DIR_ABS_PATH} {docFileAbsPath} {outputAbsPath} {TEMP_DIR_ABS_PATH}",
        CreateNoWindow  = false,
        UseShellExecute = false,
        WindowStyle     = ProcessWindowStyle.Hidden
    };

    using (Process exeProcess = Process.Start(startInfo))
    {
        // Treat conversions taking more than 30 seconds as a failure
        if (exeProcess.WaitForExit(30000)) return outputAbsPath;
        exeProcess.Kill();
        return "";
    }
}

/*
 * Serialize document model data so the Synap Editor front-end module can consume it.
 * (Important: import will fail if the body of this function is modified.)
 */
private static int[] ReadPbData(string pbFilePath)
{
    var pbData = new List<int>();
    using (var fileStream = new FileStream(pbFilePath, FileMode.Open, FileAccess.Read))
    {
        fileStream.Seek(16, SeekOrigin.Begin);
        using (var inflater = new InflaterInputStream(fileStream))
        {
            byte[] buffer = new byte[1024];
            int count;
            while ((count = inflater.Read(buffer, 0, buffer.Length)) > 0)
            {
                for (int i = 0; i < count; i++) pbData.Add(buffer[i] & 0xFF);
            }
        }
    }
    return pbData.ToArray();
}

Related Information