سؤال

يحرر: يرى رمز العمل الخاص بي في الإجابات أدناه.


باختصار: لدي ملف JSP يستدعي طريقة في Java Bean.تقوم هذه الطريقة بإنشاء ملف PDF ومن الناحية النظرية، تقوم بإعادته إلى JSP حتى يتمكن المستخدم من تنزيله.ومع ذلك، عند تحميل ملف PDF، يظهر برنامج Adobe Reader الخطأ: الملف لا يبدأ بـ "%PDF-".

بالتفصيل: حتى الآن، نجح JSP في استدعاء الطريقة، ويتم إنشاء ملف PDF ثم يظهر JSP ليمنح المستخدم ملف PDF النهائي.ومع ذلك، بمجرد أن يحاول برنامج Adobe Reader فتح ملف PDF، فإنه يعطي خطأ: الملف لا يبدأ بـ "%PDF-".لحسن الحظ، لدي طريقة لإنشاء ملف PDF على سطح المكتب الخاص بي حتى أتمكن من التحقق منه؛عندما أفتحه بشكل طبيعي داخل Windows يبدو الأمر جيدًا.فلماذا يختلف الناتج من JSP؟

لإنشاء ملف PDF، أستخدم أباتشي فوب.أنا أتبع أحد الأمثلة الأساسية، باستثناء تمرير ملف PDF الناتج إلى JSP بدلاً من حفظه على الجهاز المحلي.لقد كنت أتابعهم نمط الاستخدام الأساسي و هذا الرمز المثال.

إليك ملف JSP الخاص بي:

<%@ taglib uri="utilTLD" prefix="util" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %>
<%@ page language="java" session="false" %>
<%@ page contentType="application/pdf" %>

<%-- Construct and initialise the PrintReportsBean --%>
<jsp:useBean id="printReportsBean" scope="request" class="some.package.printreports.PrintReportsBean" />
<jsp:setProperty name="printReportsBean" property="*"/>

<c:set scope="page" var="xml" value="${printReportsBean.download}"/>

هذه هي طريقة Java Bean الخاصة بي:

//earlier in the class...
private static FopFactory fopFactory = FopFactory.newInstance();

public File getDownload() throws UtilException {

    OutputStream out = null;
    File pdf = new File("C:\\documents and settings\\me\\Desktop\\HelloWorld.pdf");
    File fo  = new File("C:\\somedirectory", "HelloWorld.fo");

    try {

        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

        out = new FileOutputStream(pdf);
        out = new BufferedOutputStream(out);

        Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer(); //identity transformer

        Source src = new StreamSource(fo);

        Result res = new SAXResult(fop.getDefaultHandler());

        transformer.transform(src, res);

        return pdf;

    } catch (Exception e) {

         throw new UtilException("Could not get download. Msg = "+e.getMessage());

    } finally {

         try {
             out.close();
         } catch (IOException io) {
             throw new UtilException("Could not close OutputStream. Msg = "+io.getMessage());
         }
    }
}

أدرك أن هذه مشكلة محددة جدًا، ولكن أي مساعدة ستكون محل تقدير كبير!

هل كانت مفيدة؟

المحلول

الطريقة التي طبقت بها هذا النوع من الميزات في الماضي هي جعل servlet يكتب محتويات ملف PDF إلى الاستجابة كدفق.لم يعد لدي كود المصدر معي بعد الآن (ولقد مر عام على الأقل منذ أن قمت بأي عمل servlet/jsp)، ولكن إليك ما قد ترغب في تجربته:

في servlet، احصل على مؤشر على تدفق إخراج الاستجابة.قم بتغيير نوع mime للاستجابة إلى "application/pdf"، واطلب من servlet القيام بمعالجة الملف الموجود في المثال الخاص بك.فقط، بدلاً من إرجاع كائن الملف، اطلب من servlet كتابة الملف إلى دفق الإخراج.شاهد أمثلة على إدخال/إخراج الملف واستبدل أي أسطر outfile.write(...) بـ ResponseStream.write(...) ويجب أن تكون جاهزًا للانطلاق.بمجرد مسح تدفق الإخراج وإغلاقه، والقيام بالإرجاع، إذا كنت أتذكر بشكل صحيح، فيجب أن يكون المتصفح قادرًا على التقاط ملف pdf من الاستجابة.

نصائح أخرى

حسنا، لقد حصلت على هذا العمل.وإليك كيف فعلت ذلك:

جسب:

<%@ taglib uri="utilTLD" prefix="util" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %>
<%@ page language="java" session="false" %>
<%@ page contentType="application/pdf" %>

<%-- Construct and initialise the PrintReportsBean --%>
<jsp:useBean id="printReportsBean" scope="request" class="some.package.PrintReportsBean" />
<jsp:setProperty name="printReportsBean" property="*"/>

<%
    // get report format as input parameter     
    ServletOutputStream servletOutputStream = response.getOutputStream();

    // reset buffer to remove any initial spaces
    response.resetBuffer(); 

    response.setHeader("Content-disposition", "attachment; filename=HelloWorld.pdf");

    // check that user is authorised to download product
    printReportsBean.getDownload(servletOutputStream);
%>

طريقة جافا فول:

//earlier in the class...
private static FopFactory fopFactory = FopFactory.newInstance();

public void getDownload(ServletOutputStream servletOutputStream) throws UtilException {

    OutputStream outputStream = null;

    File fo  = new File("C:\\some\\path", "HelloWorld.fo");

    try {

        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

        outputStream = new BufferedOutputStream(servletOutputStream);

        Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, outputStream);

        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer(); //identity transformer

        Source src = new StreamSource(fo);

        Result res = new SAXResult(fop.getDefaultHandler());

        transformer.transform(src, res);

    } catch (Exception e) {

        throw new UtilException("Could not get download. Msg = "+e.getMessage());

    } finally {

        try {
            outputStream.close();
        } catch (IOException io) {
            throw new UtilException("Could not close OutputStream. Msg = "+io.getMessage());
        }
     }
 }

شكرا للجميع علي مساهمتهم!

مجرد تخمين، ولكن هل قمت بالتحقق من نوع MIME الذي تعرضه صفحة JSP الخاصة بك؟

يحرر:إذا قرأت بالفعل الكود الذي نشرته لرأيت أنك قمت بتعيينه، فلا يهم :)

تحرير 2:ألن تنتهي الأسطر الجديدة بين علامات JSP في كود JSP الخاص بك في دفق الإخراج؟هل يمكن أن يؤدي ذلك إلى التخلص من الاستجابة التي أعادها الخادم؟لا أعرف أي شيء عن تنسيق ملف PDF، ولكن هل يعتمد ذلك على وجود أحرف "علامة" معينة في مواقع معينة في الملف؟(تبدو رسالة الخطأ التي تم إرجاعها كما هي).

أنا أتفق مع مات ب, ربما تكون هذه هي المسافات بين علامات JSP.حاول وضع التوجيه

<%@ page trimDirectiveWhitespaces="true" %>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top