Печать в определенном месте PDF с использованием iText

Я пытался получить местоположение с помощью JavaScript и передал координаты, чтобы применить штамп к штампу, но он не работает должным образом. Ниже приведена функция, которую я использовал для захвата координат указателя мыши.

function divMove(e){
    var div = document.getElementById('stamp');
    div.style.position = 'absolute';
    //div.style.top = e.clientY + 'px';
    //div.style.left = e.clientX + 'px';
    var box = div.getBoundingClientRect();
    mouse_top = e.clientY;
    mouse_left = e.clientX;
    var diff_x = mouse_left - box.left;
    var diff_y = mouse_top - box.top;
    div.style.top = ((Number(div.style.top.replace("px", "")) - 1) + diff_y) +"px";
    div.style.left = ((Number(div.style.left.replace("px", "")) - 1) + diff_x) +"px";
    document.getElementById("data").innerHTML =
        "mouse_top:" + mouse_top + "<br>mouse_left:" + mouse_left
}

Ниже приведен внутренний код для обработки штамповки с помощью iText:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
    Properties p = new Properties();
    p.load(new FileInputStream("config.properties"));

    String src = p.getProperty("src");
    String dest = p.getProperty("dest");
    String imgSrc = p.getProperty("stamp");

    PdfDocument doc = new PdfDocument(new PdfReader(src), new PdfWriter(dest));

    ImageData image = ImageDataFactory.create(imgSrc);
    float w = image.getWidth();
    float h = image.getHeight();
    System.out.println("w: " + w + ", h: " + h);

    float mouseX = Float.valueOf(request.getParameter("mouseTop"));
    float mouseY = Float.valueOf(request.getParameter("mouseLeft"));
    System.out.println("top: " + mouseX + ", left: " + mouseY);

    //Rectangle rect = new Rectangle(Math.abs(mouseX-600)+w,Math.abs(mouseY-300)+h,w,h);
    Rectangle rect = new Rectangle(mouseX,mouseY,w,h);
    PdfStampAnnotation stamp = new PdfStampAnnotation(rect).setStampName(new PdfName("Approved"));
    PdfFormXObject xObj = new PdfFormXObject(new Rectangle(w,h));
    PdfCanvas canvas = new PdfCanvas(xObj,doc);
    canvas.addImage(image,0,0,false);
    //canvas.getGraphicsState();

    stamp.setNormalAppearance(xObj.getPdfObject());
    stamp.setFlags(PdfAnnotation.PRINT);
    stamp.setFlags(PdfAnnotation.LOCKED);

    for(int i=1;i<=doc.getNumberOfPages();i++)
    {
        doc.getPage(i).addAnnotation(stamp);
    }
    //doc.getFirstPage().addAnnotation(stamp);
    FileOutputStream out = new FileOutputStream("config.properties");
    p.setProperty("src", dest);
    p.setProperty("dest", src);
    p.store(out, null);
    out.close();
    doc.close();

    //first read the file to byte array
    try
    {
        File file = new File(dest);

        if(file.canRead()){
            String base64File;

            //define the byte array to store the file
            byte[] byteFile = new byte[(int)file.length()];

            //define the stream to read the pdf
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            FileInputStream fis = new FileInputStream(file);

            //convert the read file's stream byte to base64
            //important for streaming the pdf bytes back to the front
            Base64OutputStream baos = new Base64OutputStream(bytes);

            int len;

            //read the byte from file then write it through stream to byteFile variable
            //read is reading one by one
            while((len = fis.read(byteFile)) > 0){
                baos.write(byteFile,0,len);
            }
            baos.flush();

            //turn the read byte into string
            base64File = bytes.toString("UTF-8");

            bytes.close();
            baos.close();
            fis.close();

            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition","inline");
            response.setCharacterEncoding("UTF-8");
            response.setContentLength(base64File.length());
            //write the base64 string to the response message body
            response.getWriter().write(base64File,0,base64File.length());
            //response.getOutputStream().write(base64File,0,base64File.length());

        }else{
            response.setCharacterEncoding("UTF-8");
            response.getWriter().write("File is unreadable!");
        }

    }catch(FileNotFoundException e){
        e.printStackTrace();
    }catch(Exception e){
        e.printStackTrace();
    }
    }
}

Это позиция, которую я собираюсь штамповать

Это позиция, которую я собираюсь штамповать

Выход не то, что я ожидал

Выход не то, что я ожидал

2 ответа

Этот код использует процент окна, чтобы перевести его в пользовательские единицы.

Обновить:

document.getElementById("data").innerHTML = "mouse_top:" + mouse_top
+ "<br>mouse_left:" + mouse_left

в

document.getElementById("data").innerHTML = "mouse_top:" +
(mouse_top\window.innerHeight) + "<br>mouse_left:" + (mouse_left\window.innerWidth)

На бэкэнде:

Rectange size = doc.getPage(1).getPageSize();
Rectangle rect = new Rectangle(mouseX*size.getHeight(),mouseY*size.getWidth(),w,h);

Вся суть проблемы заключается в том, чтобы определить положение и размер штампа, который вы хотите включить в PDF, относительно страницы PDF в процентах. Это именно то, что @rossfrank пытается объяснить в своем ответе и комментариях.

Если у вас есть контроль над тем, где вы используете предварительный просмотр PDF, чтобы вычислить, где должен быть размещен штамп, это может быть очень просто, например, просто примите во внимание ширину и высоту определенного кадра или даже div, если вы используете некоторые тип настраиваемого элемента для предварительного просмотра различных страниц вашего PDF-файла или очень сложный, если это зависит от фактического размера браузера, применяемого уровня масштабирования и т. д. Лучший совет - попробуйте контролировать место, в котором вы просматриваете PDF-файл.

Вероятно, вам также нужно будет передать эту эталонную ширину и высоту сервлету, потому что кажется, что вы знаете только размеры своего изображения в бэкэнде. Если это необходимо, чтобы предотвратить переполнение и т. Д.

После получения этих значений код должен быть простым:

      Properties p = new Properties();
p.load(new FileInputStream("config.properties"));

String src = p.getProperty("src");
String dest = p.getProperty("dest");
String imgSrc = p.getProperty("stamp");

PdfReader reader = new PdfReader(src);
PdfWriter writer = new PdfWriter(dest);
PdfDocument doc = new PdfDocument(reader, writer);

ImageData image = ImageDataFactory.create(imgSrc);
float w = image.getWidth();
float h = image.getHeight();
System.out.println("w: " + w + ", h: " + h);

float mouseX = Float.valueOf(request.getParameter("mouseTop"));
float mouseY = Float.valueOf(request.getParameter("mouseLeft"));

// As explained, get reference width and height values
// They can be a frame dimension, a div width and height, etcetera
float referenceWidth = Float.valueOf(request.getParameter("referenceWidth"));
float referenceHeight = Float.valueOf(request.getParameter("referenceHeight"));

// Normalize values: it can be done in the client side as well
float top    = mouseX / referenceWidth;
float left   = mouseY / referenceHeight;
float width  = w      / referenceWidth;
float height = h      / referenceHeight;

// Just in case, take into account page rotation
Rectangle pdfRectangle = reader.getPageSizeWithRotation(1);

float pdfWidth = pdfRectangle.getWidth();
float pdfHeight = pdfRectangle.getHeight();

// Please, pay attention to this code, it seems that changed in itext7
// Any way, any change should be easy
float llx = pdfWidth * left;
float lly = pdfHeight * (1 - top - height);
float urx = llx + (pdfWidth * width);
float ury = lly + (pdfHeight * height);

Rectangle rect = new Rectangle(llx, lly, urx, ury);

PdfStampAnnotation stamp = new PdfStampAnnotation(rect).setStampName(new PdfName("Approved"));
PdfFormXObject xObj = new PdfFormXObject(new Rectangle(width,height));
PdfCanvas canvas = new PdfCanvas(xObj,doc);
canvas.addImage(image,0,0,false);
//...
Другие вопросы по тегам