it-swarm.asia

تنزيل ملف من وحدات تحكم الربيع

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

ومع ذلك ، فإن مشكلتي الرئيسية هي كيف أسمح للمستخدم بتنزيل ملف من خلال Spring Controller؟

336
MilindaD
@RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET)
public void getFile(
    @PathVariable("file_name") String fileName, 
    HttpServletResponse response) {
    try {
      // get your file as InputStream
      InputStream is = ...;
      // copy it to response's OutputStream
      org.Apache.commons.io.IOUtils.copy(is, response.getOutputStream());
      response.flushBuffer();
    } catch (IOException ex) {
      log.info("Error writing file to output stream. Filename was '{}'", fileName, ex);
      throw new RuntimeException("IOError writing file to output stream");
    }

}

بشكل عام ، عندما يكون لديك response.getOutputStream() ، يمكنك كتابة أي شيء هناك. يمكنك تمرير دفق الإخراج هذا كمكان لوضعه تم إنشاؤه PDF إلى المولد الخاص بك. أيضًا ، إذا كنت تعرف نوع الملف الذي ترسله ، فيمكنك تعيينه

response.setContentType("application/pdf");
360
Infeligo

كنت قادراً على دفق هذا باستخدام الدعم المدمج في Spring مع أنه ResourceHttpMessageConverter. سيؤدي ذلك إلى تعيين طول المحتوى ونوع المحتوى إذا كان يمكنه تحديد نوع mime

@RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET)
@ResponseBody
public FileSystemResource getFile(@PathVariable("file_name") String fileName) {
    return new FileSystemResource(myService.getFileFor(fileName)); 
}
279
Scott Carlson

يجب أن تكون قادرًا على كتابة الملف على الاستجابة مباشرةً. شيء مثل

response.setContentType("application/pdf");      
response.setHeader("Content-Disposition", "attachment; filename=\"somefile.pdf\""); 

ثم اكتب الملف كدفق ثنائي في response.getOutputStream(). تذكر أن تفعل response.flush() في النهاية ويجب أن تفعل ذلك.

75
lobster1234

باستخدام Spring 3.0 ، يمكنك استخدام كائن الإرجاع HttpEntity. إذا كنت تستخدم هذا ، فلن تحتاج وحدة التحكم الخاصة بك إلى كائن HttpServletResponse ، وبالتالي يكون من الأسهل اختباره. باستثناء هذا ، هذه الإجابة تساوي إجابة Infeligo.

إذا كانت القيمة المرجعة لإطار عمل pdf الخاص بك عبارة عن صفيف بايت (اقرأ الجزء الثاني من إجابتي لقيم الإرجاع الأخرى):

@RequestMapping(value = "/files/{fileName}", method = RequestMethod.GET)
public HttpEntity<byte[]> createPdf(
                 @PathVariable("fileName") String fileName) throws IOException {

    byte[] documentBody = this.pdfFramework.createPdf(filename);

    HttpHeaders header = new HttpHeaders();
    header.setContentType(MediaType.APPLICATION_PDF);
    header.set(HttpHeaders.CONTENT_DISPOSITION,
                   "attachment; filename=" + fileName.replace(" ", "_"));
    header.setContentLength(documentBody.length);

    return new HttpEntity<byte[]>(documentBody, header);
}

إذا كان نوع الإرجاع الخاص بك PDF Framework (documentBbody) ليس بالفعل صفيف بايت ((وليس أيضًا ByteArrayInputStream) ، فسيكون من الحكمةليسإلى اجعله صفيف بايت أولاً. بدلاً من ذلك ، من الأفضل استخدام:

مثال مع FileSystemResource:

@RequestMapping(value = "/files/{fileName}", method = RequestMethod.GET)
public HttpEntity<byte[]> createPdf(
                 @PathVariable("fileName") String fileName) throws IOException {

    File document = this.pdfFramework.createPdf(filename);

    HttpHeaders header = new HttpHeaders();
    header.setContentType(MediaType.APPLICATION_PDF);
    header.set(HttpHeaders.CONTENT_DISPOSITION,
                   "attachment; filename=" + fileName.replace(" ", "_"));
    header.setContentLength(document.length());

    return new HttpEntity<byte[]>(new FileSystemResource(document),
                                  header);
}
72
Ralph

اذا أنت:

  • لا تريد تحميل الملف بالكامل في byte[] قبل إرساله إلى الرد ؛
  • تريد/تحتاج إلى إرسال/تنزيله عبر InputStream ؛
  • هل تريد التحكم الكامل في نوع Mime واسم الملف المرسلين ؛
  • اطلب من @ControllerAdvice التقاط استثناءات لك.

الكود أدناه هو ما تحتاجه:

@RequestMapping(value = "/stuff/{stuffId}", method = RequestMethod.GET)
public ResponseEntity<InputStreamResource> downloadStuff(@PathVariable int stuffId)
                                                                  throws IOException {
    String fullPath = stuffService.figureOutFileNameFor(stuffId);
    File file = new File(fullPath);

    HttpHeaders respHeaders = new HttpHeaders();
    respHeaders.setContentType("application/pdf");
    respHeaders.setContentLength(12345678);
    respHeaders.setContentDispositionFormData("attachment", "fileNameIwant.pdf");

    InputStreamResource isr = new InputStreamResource(new FileInputStream(file));
    return new ResponseEntity<InputStreamResource>(isr, respHeaders, HttpStatus.OK);
}

لاحظ أيضًا أنه لتجنب قراءة الملف بالكامل فقط لحساب طوله ، من الأفضل تخزينه مسبقًا. تأكد من مراجعة مستندات InputStreamResource .

57
acdcjunior

يعمل هذا الرمز بشكل جيد لتنزيل ملف تلقائيًا من جهاز التحكم النابض عند النقر فوق ارتباط على jsp.

@RequestMapping(value="/downloadLogFile")
public void getLogFile(HttpSession session,HttpServletResponse response) throws Exception {
    try {
        String filePathToBeServed = //complete file name with path;
        File fileToDownload = new File(filePathToBeServed);
        InputStream inputStream = new FileInputStream(fileToDownload);
        response.setContentType("application/force-download");
        response.setHeader("Content-Disposition", "attachment; filename="+fileName+".txt"); 
        IOUtils.copy(inputStream, response.getOutputStream());
        response.flushBuffer();
        inputStream.close();
    } catch (Exception e){
        LOGGER.debug("Request could not be completed at this moment. Please try again.");
        e.printStackTrace();
    }

}
17
Sunil

عملت أدناه رمز بالنسبة لي لإنشاء وتنزيل ملف نصي.

@RequestMapping(value = "/download", method = RequestMethod.GET)
public ResponseEntity<byte[]> getDownloadData() throws Exception {

    String regData = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
    byte[] output = regData.getBytes();

    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.set("charset", "utf-8");
    responseHeaders.setContentType(MediaType.valueOf("text/html"));
    responseHeaders.setContentLength(output.length);
    responseHeaders.set("Content-disposition", "attachment; filename=filename.txt");

    return new ResponseEntity<byte[]>(output, responseHeaders, HttpStatus.OK);
}
12
Siva Kumar

ما يمكنني التفكير فيه بسرعة هو إنشاء ملف pdf وتخزينه في webapp/download/<RANDOM-FILENAME> .pdf من الكود وإرسال رسالة إلى هذا الملف باستخدام HttpServletRequest

request.getRequestDispatcher("/downloads/<RANDOM-FILENAME>.pdf").forward(request, response);

أو إذا كان يمكنك تكوين محلل العرض الخاص بك شيء من هذا القبيل ،

  <bean id="pdfViewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass"
              value="org.springframework.web.servlet.view.JstlView" />
    <property name="order" value=”2″/>
    <property name="prefix" value="/downloads/" />
    <property name="suffix" value=".pdf" />
  </bean>

ثم العودة فقط

return "RANDOM-FILENAME";
5
kalyan

شيء مثل أدناه

@RequestMapping(value = "/download", method = RequestMethod.GET)
public void getFile(HttpServletResponse response) {
    try {
        DefaultResourceLoader loader = new DefaultResourceLoader();
        InputStream is = loader.getResource("classpath:META-INF/resources/Accepted.pdf").getInputStream();
        IOUtils.copy(is, response.getOutputStream());
        response.setHeader("Content-Disposition", "attachment; filename=Accepted.pdf");
        response.flushBuffer();
    } catch (IOException ex) {
        throw new RuntimeException("IOError writing file to output stream");
    }
}

يمكنك عرض PDF أو تنزيله أمثلة هنا

2
xxy

الحل التالي يعمل بالنسبة لي

    @RequestMapping(value="/download")
    public void getLogFile(HttpSession session,HttpServletResponse response) throws Exception {
        try {

            String fileName="archivo demo.pdf";
            String filePathToBeServed = "C:\\software\\Tomcat 7.0\\tmpFiles\\";
            File fileToDownload = new File(filePathToBeServed+fileName);

            InputStream inputStream = new FileInputStream(fileToDownload);
            response.setContentType("application/force-download");
            response.setHeader("Content-Disposition", "attachment; filename="+fileName); 
            IOUtils.copy(inputStream, response.getOutputStream());
            response.flushBuffer();
            inputStream.close();
        } catch (Exception exception){
            System.out.println(exception.getMessage());
        }

    }
1
Jorge Santos Neill

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

response.setContentType("application/force-download");
0
Sagar Nair