Преобразование HTML-файла в PDF-документ в iOS с помощью Cocoa-Touch - PullRequest
3 голосов
/ 11 июня 2011

Я хочу конвертировать локальный HTML-файл на iPhone в PDF-документ.Я использовал следующий код, который я нашел в Интернете, чтобы сгенерировать PDF-файл из Picture, я попытался заменить изображение html-файлом, но это не удалось.Я был бы очень признателен за вашу помощь.Заранее спасибо,

// Our method to create a PDF file natively on the iPhone
// This method takes two parameters, a CGRect for size and
// a const char, which will be the name of our pdf file
void CreatePDFFile (CGRect pageRect, const char *filename) {

    // This code block sets up our PDF Context so that we can draw to it
    CGContextRef pdfContext;
    CFStringRef path;
    CFURLRef url;
    CFMutableDictionaryRef myDictionary = NULL;
    // Create a CFString from the filename we provide to this method when we call it
    path = CFStringCreateWithCString (NULL, filename,
                                      kCFStringEncodingUTF8);
    // Create a CFURL using the CFString we just defined
    url = CFURLCreateWithFileSystemPath (NULL, path,
                                         kCFURLPOSIXPathStyle, 0);
    CFRelease (path);
    // This dictionary contains extra options mostly for 'signing' the PDF
    myDictionary = CFDictionaryCreateMutable(NULL, 0,
                                             &kCFTypeDictionaryKeyCallBacks,
                                             &kCFTypeDictionaryValueCallBacks);
    CFDictionarySetValue(myDictionary, kCGPDFContextTitle, CFSTR("My PDF File"));
    CFDictionarySetValue(myDictionary, kCGPDFContextCreator, CFSTR("My Name"));
    // Create our PDF Context with the CFURL, the CGRect we provide, and the above defined dictionary
    pdfContext = CGPDFContextCreateWithURL (url, &pageRect, myDictionary);
    // Cleanup our mess
    CFRelease(myDictionary);
    CFRelease(url);
    // Done creating our PDF Context, now it's time to draw to it

    // Starts our first page
    CGContextBeginPage (pdfContext, &pageRect);

    // Draws a black rectangle around the page inset by 50 on all sides
    CGContextStrokeRect(pdfContext, CGRectMake(50, 50, pageRect.size.width - 100, pageRect.size.height - 100));

    // This code block will create an image that we then draw to the page
    const char *picture = "Picture";
    CGImageRef image;
    CGDataProviderRef provider;
    CFStringRef picturePath;
    CFURLRef pictureURL;

    picturePath = CFStringCreateWithCString (NULL, picture,
                                      kCFStringEncodingUTF8);
    pictureURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), picturePath, CFSTR("png"), NULL);
    CFRelease(picturePath);
    provider = CGDataProviderCreateWithURL (pictureURL);
    CFRelease (pictureURL);
    image = CGImageCreateWithPNGDataProvider (provider, NULL, true, kCGRenderingIntentDefault);
    CGDataProviderRelease (provider);
    CGContextDrawImage (pdfContext, CGRectMake(200, 200, 207, 385),image);
    CGImageRelease (image);


    // End image code

    // Adding some text on top of the image we just added
    CGContextSelectFont (pdfContext, "Helvetica", 16, kCGEncodingMacRoman);
    CGContextSetTextDrawingMode (pdfContext, kCGTextFill);
    CGContextSetRGBFillColor (pdfContext, 0, 0, 0, 1);
    const char *text = "Hello World!";
    CGContextShowTextAtPoint (pdfContext, 260, 390, text, strlen(text));
    // End text

    // We are done drawing to this page, let's end it
    // We could add as many pages as we wanted using CGContextBeginPage/CGContextEndPage
    CGContextEndPage (pdfContext);

    // We are done with our context now, so we release it
    CGContextRelease (pdfContext);
}

- (IBAction)createPDF:(id)sender {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *saveDirectory = [paths objectAtIndex:0];
    NSString *saveFileName = @"myPDF.pdf";
    NSString *newFilePath = [saveDirectory stringByAppendingPathComponent:saveFileName];
    const char *filename = [newFilePath UTF8String];
    CreatePDFFile(CGRectMake(0, 0, 612, 792),filename);
}

Ответы [ 2 ]

7 голосов
/ 17 ноября 2012

Я создал класс, основываясь на каждом хорошем совете, который нашел. Я много копаю и надеюсь, что мой класс послужит хорошим началом для тех, кто пытается создать многостраничный PDF-файл непосредственно из какого-либо HTML-источника.

Здесь вы найдете весь код с некоторыми базовыми примерами кода: https://github.com/iclems/iOS-htmltopdf

У меня была та же проблема, что и у вас, и мои требования были: - полный PDF (реальный текст, без растрового изображения) - умные многостраничные (по сравнению с разрезанием веб-просмотра на полную высоту каждые X пикселей ...)

Таким образом, решение, которое я использую, довольно приятно, поскольку оно использует те же инструменты, которые использует iOS для разделения страниц для печати. ​​

Позвольте мне объяснить, я установил UIPrintPageRenderer на основе форматера печати веб-представления (первый совет):

UIPrintPageRenderer *render = [[UIPrintPageRenderer alloc] init];

[render addPrintFormatter:webView.viewPrintFormatter startingAtPageAtIndex:0];

CGRect printableRect = CGRectMake(self.pageMargins.left,
                              self.pageMargins.top,
                              self.pageSize.width - self.pageMargins.left - self.pageMargins.right,
                              self.pageSize.height - self.pageMargins.top - self.pageMargins.bottom);

CGRect paperRect = CGRectMake(0, 0, self.pageSize.width, self.pageSize.height);

[render setValue:[NSValue valueWithCGRect:paperRect] forKey:@"paperRect"];
[render setValue:[NSValue valueWithCGRect:printableRect] forKey:@"printableRect"];

NSData *pdfData = [render printToPDF];

[pdfData writeToFile: self.PDFpath  atomically: YES];

Тем временем я создал категорию для поддержки UIPrintPageRenderer:

-(NSData*) printToPDF
{
    [self doNotRasterizeSubviews:self.view];

    NSMutableData *pdfData = [NSMutableData data];

    UIGraphicsBeginPDFContextToData( pdfData, CGRectZero, nil );

    [self prepareForDrawingPages: NSMakeRange(0, self.numberOfPages)];

    CGRect bounds = UIGraphicsGetPDFContextBounds();

    for ( int i = 0 ; i < self.numberOfPages ; i++ )
    {
        UIGraphicsBeginPDFPage();

        [self drawPageAtIndex: i inRect: bounds];
    }

    UIGraphicsEndPDFContext();

    return pdfData;
}
6 голосов
/ 11 июня 2011

Чтобы преобразовать HTML в PDF, вам необходимо:

  • Создать веб-просмотр и загрузить HTML.
  • Снять захват веб-просмотра.
  • Конвертировать его в PDFфайл.

Второй шаг (захват веб-просмотра) должен быть сделан после загрузки содержимого веб-просмотра. Для этого захвата вы можете найти образец, как в Как сделать снимок экрана UIView? Затем вы используете этот контекст для преобразования в файл PDF.

Для веб-просмотра вам не нужно его показывать, просто создайте его без добавления представления на экране.

Редактировать: Другие детали: для высоты веб-просмотра вы можете рассчитать высоту содержимого веб-просмотра и изменить фрейм веб-просмотра

- (void)webViewDidFinishLoad:(UIWebView *)theWebView {
    NSUInteger contentHeight = [[theWebView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"document.body.scrollHeight;"]] intValue];
    NSUInteger contentWidth = [[theWebView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"document.body.scrollWidth;"]] intValue];
    [theWebView setFrame:CGRectMake(0, 0, contentWidth, contentHeight)];
}
...