【问题标题】:How to display pdf document from the web service?如何从 Web 服务显示 pdf 文档?
【发布时间】:2012-11-29 09:38:42
【问题描述】:

我从 Web 服务获得一个 NSString,我使用 dataWithBase64EncodedString 方法将其转换为 NSData,然后使用以下代码将 NSData 转换为 pdf:

CFDataRef myPDFData = (__bridge CFDataRef) retrievedData;
    CGDataProviderRef provider = CGDataProviderCreateWithCFData(myPDFData);
    CGPDFDocumentRef pdf = (CGPDFDocumentCreateWithProvider(provider));

现在我不知道如何在 iPhone 的屏幕上显示这个 pdf。

+ (id)dataWithBase64EncodedString:(NSString *)string;
{
if (string == nil)
    [NSException raise:NSInvalidArgumentException format:nil];
if ([string length] == 0)
    return [NSData data];

static char *decodingTable = NULL;
if (decodingTable == NULL)
{
    decodingTable = malloc(256);
    if (decodingTable == NULL)
        return nil;
    memset(decodingTable, CHAR_MAX, 256);
    NSUInteger i;
    for (i = 0; i < 64; i++)
        decodingTable[(short)encodingTable[i]] = i;
}

const char *characters = [string cStringUsingEncoding:NSASCIIStringEncoding];
if (characters == NULL)     //  Not an ASCII string!
    return nil;
char *bytes = malloc((([string length] + 3) / 4) * 3);
if (bytes == NULL)
    return nil;
NSUInteger length = 0;

NSUInteger i = 0;
while (YES)
{
    char buffer[4];
    short bufferLength;
    for (bufferLength = 0; bufferLength < 4; i++)
    {
        if (characters[i] == '\0')
            break;
        if (isspace(characters[i]) || characters[i] == '=')
            continue;
        buffer[bufferLength] = decodingTable[(short)characters[i]];
        if (buffer[bufferLength++] == CHAR_MAX)      //  Illegal character!
        {
            free(bytes);
            return nil;
        }
    }

    if (bufferLength == 0)
        break;
    if (bufferLength == 1)      //  At least two characters are needed to produce one byte!
    {
        free(bytes);
        return nil;
    }

    //  Decode the characters in the buffer to bytes.
    bytes[length++] = (buffer[0] << 2) | (buffer[1] >> 4);
    if (bufferLength > 2)
        bytes[length++] = (buffer[1] << 4) | (buffer[2] >> 2);
    if (bufferLength > 3)
        bytes[length++] = (buffer[2] << 6) | buffer[3];
}

realloc(bytes, length);
return [NSData dataWithBytesNoCopy:bytes length:length];
}

【问题讨论】:

    标签: iphone pdf


    【解决方案1】:

    创建一个上下文,如果你没有,然后为给定的页面 (index) 做:

    - (void)drawPDF:(CGPDFDocumentRef)pdf pageIndex:(NSUInteger)index context:(CGContextRef)ctx {
    
        CGPDFPageRef page = CGPDFDocumentGetPage(pdf, index);
        CGAffineTransform transform = aspectFit(CGPDFPageGetBoxRect(page, kCGPDFMediaBox),
                                            CGContextGetClipBoundingBox(ctx));
        CGContextConcatCTM(ctx, transform);
        CGContextDrawPDFPage(ctx, page);
    }
    

    要获得一个上下文,你可以这样做:

    CGSize pageSize = ...;
    UIGraphicsBeginImageContextWithOptions(pageSize, YES, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextClipToRect(context, CGRectMake(0, 0, pageSize.width, pageSize.height));
    
        <DRAW PAGE HERE>
        [self drawPDF:pdf pageIndex:N context:context];
    
    UIGraphicsEndImageContext();
    

    编辑,您还应该定义以下 C 函数(在任何类之外)处理将 PDF 缩放到视图大小:

    CGAffineTransform aspectFit(CGRect innerRect, CGRect outerRect) {
      CGFloat scaleFactor = MIN(outerRect.size.width/innerRect.size.width, outerRect.size.height/innerRect.size.height);
      CGAffineTransform scale = CGAffineTransformMakeScale(scaleFactor, scaleFactor);
      CGRect scaledInnerRect = CGRectApplyAffineTransform(innerRect, scale);
      CGAffineTransform translation = 
      CGAffineTransformMakeTranslation((outerRect.size.width - scaledInnerRect.size.width) / 2 - scaledInnerRect.origin.x, 
                                     (outerRect.size.height - scaledInnerRect.size.height) / 2 - scaledInnerRect.origin.y);
      return CGAffineTransformConcat(scale, translation);
    }
    

    或者,您可以删除这些行:

        CGAffineTransform transform = aspectFit(CGPDFPageGetBoxRect(page, kCGPDFMediaBox),
                                            CGContextGetClipBoundingBox(ctx));
        CGContextConcatCTM(ctx, transform);
    

    【讨论】:

    • 谢谢。:) 我应该用特定的方法编写这段代码并调用它吗?因为 xcode 无法识别 ctx 和其他变量。对不起,如果这是一个愚蠢的问题。
    • 虽然这是绘制 PDF 的正确方法,但您可能需要考虑其他一些建议,例如使用 UIWebView 或 QuickView。或者,如果您正在使用 Core Graphics 来显示您的 PDF,请使用平铺视图。这是因为如果您的 PDF 特别大,那么在内存和速度方面,您会遇到问题。
    • @sergio 抱歉打扰了。我收到错误函数'aspectFit'的隐式声明在C99中无效。使用不兼容类型“int”的表达式初始化“CGAffineTransform”。你知道为什么吗?
    【解决方案2】:

    您可以在 UIWebview 中加载您的 pdf 文件,该文件将显示其具有许多 pdf 阅读器功能。

    【讨论】:

      猜你喜欢
      • 2011-08-01
      • 2010-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-17
      • 2015-12-11
      • 1970-01-01
      • 2021-05-18
      相关资源
      最近更新 更多