"اسم" ملف pdf على الويب للحصول على اسم ملف افتراضي أفضل لحفظه في Acrobat؟

StackOverflow https://stackoverflow.com/questions/151079

سؤال

يقوم تطبيقي بإنشاء ملفات PDF لاستهلاك المستخدم.تم تعيين رأس http "الترتيب للمحتوى" كما هو مذكور هنا.تم ضبط هذا على "مضمّن؛filename=foo.pdf"، والذي يجب أن يكون كافيًا لكي يقوم Acrobat بإعطاء "foo.pdf" كاسم ملف عند حفظ ملف pdf.

ومع ذلك، عند النقر فوق الزر "حفظ" في Acrobat المضمن في المتصفح، فإن الاسم الافتراضي المراد حفظه ليس اسم الملف هذا ولكن بدلاً من ذلك تم تغيير عنوان URL الذي يحتوي على شرطات مائلة إلى شرطة سفلية.ضخمة وقبيحة.هل هناك طريقة للتأثير على اسم الملف الافتراضي هذا في Adobe؟

توجد سلسلة استعلام في عناوين URL، وهذا غير قابل للتفاوض.قد يكون هذا مهمًا، ولكن إضافة "&foo=/title.pdf" إلى نهاية عنوان URL لا يؤثر على اسم الملف الافتراضي.

التحديث 2:لقد حاولت على حد سواء

content-disposition  inline; filename=foo.pdf
Content-Type         application/pdf; filename=foo.pdf

و

content-disposition  inline; filename=foo.pdf
Content-Type         application/pdf; name=foo.pdf

(كما تم التحقق من خلال Firebug) للأسف، لم ينجح أي منهما.

عنوان URL عينة هو

/bar/sessions/958d8a22-0/views/1493881172/export?format=application/pdf&no-attachment=true

والذي يُترجم إلى حفظ Acrobat الافتراضي باسم ملف

http___localhost_bar_sessions_958d8a22-0_views_1493881172_export_format=application_pdf&no-attachment=true.pdf

التحديث 3:يقدم جوليان ريشكي رؤية ودقة حقيقية لهذه القضية.يرجى التصويت لصالح إجابته.يبدو أن هذا معطل في FF (https://bugzilla.mozilla.org/show_bug.cgi?id=433613) وIE ولكنها تعمل في Opera وSafari وChrome. http://greenbytes.de/tech/tc2231/#inlwithasciifilenamepdf

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

المحلول

جزء من المشكلة هو أن ذات الصلة آر إف سي 2183 لا يوضح حقًا ما يجب فعله بنوع التصرف "المضمن" واسم الملف.

أيضًا، بقدر ما أستطيع أن أقول، فإن UA الوحيد الذي يستخدم بالفعل اسم الملف لـ type=inline هو Firefox (راجع حالة اختبار).

أخيرًا، ليس من الواضح أن واجهة برمجة التطبيقات الإضافية تجعل هذه المعلومات متاحة بالفعل (ربما يستطيع شخص مطلع على واجهة برمجة التطبيقات توضيح ذلك).

ومع ذلك، لقد أرسلت مؤشرًا لهذا السؤال إلى أحد مستخدمي Adobe؛ربما سيلقي الأشخاص المناسبون نظرة.

متعلق ب:راجع محاولة توضيح ترتيب المحتوى في HTTP في مسودة-reschke-rfc2183-in-http - هذا هو العمل المبكر قيد التقدم، ونقدر التعليقات.

تحديث:لقد أضفت أ حالة اختبار, ، والذي يبدو أنه يشير إلى أن المكون الإضافي لـ Acrobat Reader لا يستخدم رؤوس الاستجابة (في Firefox)، على الرغم من أن واجهة برمجة تطبيقات البرنامج الإضافي توفر الوصول إليها.

نصائح أخرى

تعيين اسم الملف في نوع المحتوى أيضًا.هذا يجب أن يحل المشكلة.

context.Response.ContentType = "application/pdf; name=" + fileName;
// the usual stuff
context.Response.AddHeader("content-disposition", "inline; filename=" + fileName);

بعد تعيين رأس ترتيب المحتوى، قم أيضًا بإضافة رأس طول المحتوى، ثم استخدم الكتابة الثنائية لدفق ملف PDF.

context.Response.AddHeader("Content-Length", fileBytes.Length.ToString());
context.Response.BinaryWrite(fileBytes);

لقد حاولت وحاولت، مثلك، أن أنجح في هذا الأمر.وأخيرا تخليت عن هذه الفكرة، واخترت الحل البديل.

أنا أستخدم ASP.NET MVC Framework، لذلك قمت بتعديل المسارات الخاصة بوحدة التحكم/الإجراء للتأكد من أن ملف PDF المقدم هو الجزء الأخير من جزء الموقع من URI (قبل سلسلة الاستعلام)، وتمرير كل شيء آخر في سلسلة الاستعلام.

على سبيل المثال:

عنوان URL القديم:

http://server/app/report/showpdf?param1=foo&param2=bar&filename=myreport.pdf

عنوان URL الجديد:

http://server/app/report/showpdf/myreport.pdf?param1=foo&param2=bar

يبدو الرأس الناتج تمامًا مثل ما وصفته (نوع المحتوى هو application/pdf، والتصرف مضمن، واسم الملف جزء غير مفيد من الرأس).يعرضه Acrobat في نافذة المتصفح (لا يوجد مربع حوار حفظ باسم) ويكون اسم الملف الذي يتم ملؤه تلقائيًا إذا قام المستخدم بالنقر فوق الزر Acrobat Save هو اسم ملف التقرير.

بعض الاعتبارات:

لكي تبدو أسماء الملفات لائقة، يجب ألا تحتوي على أي أحرف هاربة (على سبيل المثال، بدون مسافات، وما إلى ذلك)...وهو ما يحد قليلا.يتم إنشاء أسماء الملفات الخاصة بي تلقائيًا في هذه الحالة، وقبل ذلك كانت تحتوي على مسافات، والتي كانت تظهر كـ "%20" في اسم ملف مربع حوار الحفظ الناتج.لقد قمت للتو باستبدال المسافات بشرطات سفلية، وقد نجح الأمر.

هذا ليس هو الحل الأفضل بأي حال من الأحوال، لكنه يعمل.ويعني ذلك أيضًا أنه يجب أن يكون لديك اسم الملف متاحًا لجعله جزءًا من عنوان URI الأصلي، مما قد يفسد سير عمل البرنامج.إذا كان يتم إنشاؤه أو استرداده حاليًا من قاعدة بيانات أثناء الاستدعاء من جانب الخادم الذي يقوم بإنشاء ملف PDF، فقد تحتاج إلى نقل التعليمات البرمجية التي تنشئ اسم الملف إلى جافا سكريبت كجزء من إرسال النموذج أو إذا كان يأتي من قاعدة بيانات فاجعله استدعاء ajax سريع للحصول على اسم الملف عند إنشاء عنوان URL الذي ينتج عنه ملف PDF المضمن.

إذا كنت تأخذ اسم الملف من إدخال مستخدم في نموذج، فيجب التحقق من صحة ذلك بحيث لا يحتوي على أحرف تم تجاوزها، مما قد يزعج المستخدمين.

امل ان يساعد.

حاول وضع اسم الملف في نهاية عنوان URL، قبل أي معلمات أخرى.لقد نجح هذا بالنسبة لي.http://www.setasign.de/support/tips-and-tricks/filename-in-browser-plugin/

في ASP.NET 2.0، قم بتغيير عنوان URL من

http://www. server.com/DocServe.aspx?DocId=XXXXXXX

ل

http://www. server.com/DocServe.aspx/MySaveAsFileName?DocId=XXXXXXX

يعمل هذا مع Acrobat 8 ​​واسم ملف SaveAs الافتراضي هو الآن MySaveAsFileName.pdf.

ومع ذلك، يجب عليك تقييد الأحرف المسموح بها MySaveAsFileName (بدون فترات، وما إلى ذلك).

أباتشي mod_rewrite يمكن حل هذا.

لدي خدمة ويب مع نقطة النهاية في /foo/getDoc.service.بالطبع سوف يقوم Acrobat بحفظ الملفات بتنسيق getDoc.pdf.أضفت الأسطر التالية في apache.conf:

LoadModule     RewriteModule         modules/mod_rewrite.so
RewriteEngine  on
RewriteRule    ^/foo/getDoc/(.*)$    /foo/getDoc.service     [P,NE]

الآن عندما أطلب /foo/getDoc/filename.pdf?bar&qux, ، تتم إعادة كتابته داخليًا إلى /foo/getDoc.service?bar&qux, ، لذا فإنني أصل إلى نقطة النهاية الصحيحة لخدمة الويب، لكن Acrobat يعتقد أنه سيحفظ ملفي باسم filename.pdf.

إذا كنت تستخدم asp.net، فيمكنك التحكم في اسم ملف pdf من خلال اسم ملف الصفحة (url).كما كتب مستخدمون آخرون، فإن Acrobat بسيط بعض الشيء...عند اختيار اسم ملف pdf عند الضغط على زر "حفظ":يأخذ اسم الصفحة ويزيل الامتداد ويضيف ".pdf".لذلك /foo/bar/GetMyPdf.aspx يعطي GetMyPdf.pdf.

الحل الوحيد الذي وجدته هو إدارة أسماء الصفحات "الديناميكية" من خلال معالج asp.net:

  • إنشاء فئة تطبق IHttpHandler
  • قم بتعيين معالج في web.config يحده الفصل

رسم الخرائط 1:جميع الصفحات لها جذر مشترك (MyDocument_):

<httpHandlers>  
<add verb="*" path="MyDocument_*.ashx" type="ITextMiscWeb.MyDocumentHandler"/>

رسم الخرائط 2:اسم ملف مجاني تمامًا (يحتاج إلى مجلد في المسار):

<add verb="*" path="/CustomName/*.ashx" type="ITextMiscWeb.MyDocumentHandler"/>

بعض النصائح هنا (يتم إنشاء ملف pdf ديناميكيًا باستخدام iTextSharp):
http://fhtino.blogspot.com/2006/11/how-to-show-or-download-pdf-file-from.html

بدلاً من المرفقات، يمكنك تجربة ما يلي:

Response.AddHeader("content-disposition", "inline;filename=MyFile.pdf");

لقد استخدمته بشكل مضمن في تطبيق ويب سابق قام بإنشاء مخرجات Crystal Reports إلى PDF وأرسلها في المتصفح إلى المستخدم.

مربع حوار تنزيل الملف (PDF) مع خيار الحفظ والفتح

نقطة لنتذكر:

  1. إرجاع الدفق بحجم الصفيف الصحيح من الخدمة
  2. اقرأ مصفوفة البايت من الدفق بطول البايت الصحيح على أساس طول الدفق.
  3. تعيين نوع المحتوى الصحيح

إليك رمز دفق القراءة وفتح مربع حوار تنزيل الملف لملف PDF

private void DownloadSharePointDocument()
{
    Uri uriAddress = new Uri("http://hyddlf5187:900/SharePointDownloadService/FulfillmentDownload.svc/GetDocumentByID/1/drmfree/");
    HttpWebRequest req = WebRequest.Create(uriAddress) as HttpWebRequest;
    // Get response   
    using (HttpWebResponse httpWebResponse = req.GetResponse() as HttpWebResponse)
    {
        Stream stream = httpWebResponse.GetResponseStream();
        int byteCount = Convert.ToInt32(httpWebResponse.ContentLength);
        byte[] Buffer1 = new byte[byteCount];
        using (BinaryReader reader = new BinaryReader(stream))
        {
            Buffer1 = reader.ReadBytes(byteCount);
        }
        Response.Clear();
        Response.ClearHeaders();
        // set the content type to PDF 
        Response.ContentType = "application/pdf";
        Response.AddHeader("Content-Disposition", "attachment;filename=Filename.pdf");
        Response.Buffer = true;
        Response.BinaryWrite(Buffer1);
        Response.Flush();
       // Response.End();
    }
}

أعتقد أن هذا قد تم ذكره بالفعل بطريقة أو بأخرى ولكني سأحاول أن أذكره بكلماتي الخاصة.

بدلا من ذلك:

/bar/sessions/958d8a22-0/views/1493881172/export?format=application/pdf&no-attachment=true

انا استعمل هذا:

/bar/sessions/958d8a22-0/views/1493881172/NameThatIWantPDFToBe.pdf?GeneratePDF=1

بدلاً من "تصدير" معالجة الطلب، عندما يأتي طلب، أبحث في عنوان URL عن GeneratePDF=1.إذا تم العثور عليه، أقوم بتشغيل أي رمز كان قيد التشغيل في "التصدير" بدلاً من السماح لنظامي بمحاولة البحث عن ملف PDF وتقديمه في الموقع /bar/sessions/958d8a22-0/views/1493881172/NameThatIWantPDFToBe.pdf.إذا لم يتم العثور على GeneratePDF في عنوان URL، فأنا ببساطة أقوم بإرسال الملف المطلوب.(لاحظ أنه لا يمكنني ببساطة إعادة التوجيه إلى الملف المطلوب - وإلا فسينتهي بي الأمر في حلقة لا نهاية لها)

يمكن أن يكون لديك دائمًا رابطان.أحدهما يفتح المستند داخل المتصفح، والآخر لتنزيله (باستخدام نوع محتوى غير صحيح).هذا ما يفعله Gmail.

لأي شخص لا يزال ينظر إلى هذا، استخدمت الحل الموجود هنا وقد عملت بشكل رائع.شكرا فابريزيو!

الطريقة التي قمت بحلها (باستخدام PHP) هي كما يلي:

لنفترض أن عنوان URL الخاص بك هو SomeScript.php?id=ID&data=DATA والملف الذي تريد استخدامه هو TEST.pdf.

قم بتغيير عنوان URL إلى SomeScript.php/id/ID/data/DATA/EXT/TEST.pdf.

من المهم أن تكون المعلمة الأخيرة هي اسم الملف الذي تريد أن يستخدمه Adobe (يمكن أن يكون "EXT" يتعلق بأي شيء).تأكد من عدم وجود أحرف خاصة في السلسلة أعلاه، راجع للشغل.

الآن، في الجزء العلوي من SomeScript.php, ، يضيف:

$_REQUEST = MakeFriendlyURI( $_SERVER['PHP\_SELF'], $_SERVER['SCRIPT_FILENAME']);

ثم أضف هذه الوظيفة إلى SomeScript.php (أو مكتبة الوظائف الخاصة بك):

function MakeFriendlyURI($URI, $ScriptName) {

/* Need to remove everything up to the script name */
$MyName = '/^.*'.preg_quote(basename($ScriptName)."/", '/').'/';
$Str = preg_replace($MyName,'',$URI);
$RequestArray = array();

/* Breaks down like this
      0      1     2     3     4     5
    PARAM1/VAL1/PARAM2/VAL2/PARAM3/VAL3
*/

$tmp = explode('/',$Str);   
/* Ok so build an associative array with Key->value
   This way it can be returned back to $_REQUEST or $_GET
 */
for ($i=0;$i < count($tmp); $i = $i+2){
    $RequestArray[$tmp[$i]] = $tmp[$i+1];
}
return $RequestArray;       
}//EO MakeFriendlyURI

الآن $_REQUEST (أو $_GET إذا كنت تفضل ذلك) يتم الوصول إليه كالمعتاد $_REQUEST['id'], $_REQUEST['data'], ، إلخ.

وستستخدم Adobe اسم الملف المطلوب باعتباره حفظ افتراضي باسم أو معلومات البريد الإلكتروني عند إرساله مضمّنًا.

تمت إعادة توجيهي هنا لأن لدي نفس المشكلة.لقد جربت أيضًا الحل البديل الخاص بـ Troy Howard ولكن يبدو أنه لا يعمل.

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

http://forums.asp.net/t/143631.aspx

آمل أن يكون شرحي المبهم قد أعطاك فكرة.

الشكر ل فيفيك.


نجينكس

location /file.pdf
{
    # more_set_headers "Content-Type: application/pdf; name=save_as_file.pdf";
    add_header Content-Disposition "inline; filename=save_as_file.pdf";
    alias /var/www/file.pdf;
}

تحقق مع

curl -I https://example.com/file.pdf

فايرفوكس 62.0b5 (64 بت):نعم.

كروم 67.0.3396.99 (64 بت):نعم.

إي 11:لا تعليق.

جرب هذا، إذا كان ملفك القابل للتنفيذ هو "get.cgi"

http://server,org/get.cgi/filename.pdf?file=filename.pdf

نعم، إنه مجنون تماما.لا يوجد ملف يسمى "filename.pdf" على الخادم، يوجد دليل على الإطلاق ضمن ملف get.cgi القابل للتنفيذ.

يبدو أنه يعمل.يتجاهل الخادم ملف filename.pdf ويتجاهل قارئ pdf ملف "get.cgi"

دان

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top