image.png (429.8 KB)
the first image when i try to upload docx and after convert to html i am using tool to show as pdf it is showing single layout rather than double side layout
export class ConversionService {
private readonly tempDir: string;
private readonly asposeClientId: string | undefined;
private readonly asposeClientSecret: string | undefined;
private readonly useAspose: boolean;
constructor() {
// Set temp directory for conversions
this.tempDir = path.join(process.cwd(), 'uploads', 'temp', 'conversions');
// Aspose.Words Cloud API credentials (required)
this.asposeClientId = process.env.ASPOSE_CLIENT_ID || undefined;
this.asposeClientSecret = process.env.ASPOSE_CLIENT_SECRET || undefined;
this.useAspose = process.env.USE_ASPOSE === 'true' && !!this.asposeClientId && !!this.asposeClientSecret;
// Aspose configuration initialized
// Ensure temp directory exists (fire and forget)
void this.ensureTempDir();
}
/**
* Ensure temp directory exists
*/
private async ensureTempDir(): Promise<void> {
try {
await fs.mkdir(this.tempDir, { recursive: true });
} catch (error) {
console.error('[ConversionService] Failed to create temp directory:', error);
}
}
/**
* Convert DOCX file to HTML using Aspose Words Cloud API only
*/
async convertDocxToHtml(filePath: string): Promise<string> {
// Use Aspose only (no fallbacks)
if (this.useAspose) {
return await this.convertDocxToHtmlWithAspose(filePath);
} else {
throw new Error('Aspose.Words Cloud API not configured. Cannot convert DOCX to HTML.');
}
}
/**
* Convert DOCX to HTML using Aspose.Words Cloud API
* This method preserves headers, footers, and page templates better than other methods
*/
private async convertDocxToHtmlWithAspose(filePath: string): Promise<string> {
try {
if (!this.asposeClientId || !this.asposeClientSecret) {
throw new Error('Aspose credentials not configured');
}
// Get access token
const tokenResponse = await axios.post(
'https://api.aspose.cloud/connect/token',
new URLSearchParams({
grant_type: 'client_credentials',
client_id: this.asposeClientId,
client_secret: this.asposeClientSecret,
}),
{
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
}
);
const accessToken = tokenResponse.data.access_token;
// Upload file to Aspose Cloud Storage
const fileName = `temp_${Date.now()}_${path.basename(filePath)}`;
const fileBuffer = await fs.readFile(filePath);
await axios.put(
`https://api.aspose.cloud/v4.0/words/storage/file/${fileName}`,
fileBuffer,
{
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/octet-stream',
},
}
);
// File uploaded, converting to HTML
const convertResponse = await axios.get(
`https://api.aspose.cloud/v4.0/words/${fileName}`,
{
params: {
format: 'html',
// Options to preserve document structure
exportHeadersFootersMode: 'PerSection', // Export headers/footers for each section
exportImagesAsBase64: true, // Embed images as base64
},
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: 'application/json',
},
responseType: 'arraybuffer',
}
);
const htmlContent = Buffer.from(convertResponse.data).toString('utf-8');
// Clean up - delete file from Aspose Cloud Storage
try {
await axios.delete(
`https://api.aspose.cloud/v4.0/words/storage/file/${fileName}`,
{
headers: { Authorization: `Bearer ${accessToken}` },
}
);
// Cleaned up Aspose Cloud storage
} catch (cleanupError) {
// Silently ignore cleanup errors
}
return htmlContent;
} catch (error) {
throw error;
}
}