ভূমিকা
আপনি সব মাধ্যমে পেতে পারেন ExternalContext
। জেএসএফ 1.x এ আপনি কাঁচা HttpServletResponse
বস্তুটি পেতে পারেন ExternalContext#getResponse()
। জেএসএফ ২.x এ, আপনি জেএসএফ হুডের অধীনে থেকে ExternalContext#getResponseOutputStream()
দখল HttpServletResponse
গ্রহণের প্রয়োজন ছাড়াই নতুন প্রতিনিধি পদ্ধতির গুচ্ছ ব্যবহার করতে পারেন ।
প্রতিক্রিয়ায়, আপনার শিরোনামটি সেট করা উচিত Content-Type
যাতে ক্লায়েন্ট জানে যে সরবরাহিত ফাইলটির সাথে কোন অ্যাপ্লিকেশনটি সংযুক্ত করতে হবে। এবং, আপনার Content-Length
শিরোনাম সেট করা উচিত যাতে ক্লায়েন্টটি ডাউনলোডের অগ্রগতি গণনা করতে পারে, অন্যথায় এটি অজানা। এবং, আপনি যেমন সংরক্ষণ করুন ডায়ালগ চান তবে আপনাকে Content-Disposition
শিরোনামটি সেট করা উচিত , অন্যথায় ক্লায়েন্টটি ইনলাইনটি প্রদর্শন করার চেষ্টা করবে। পরিশেষে কেবল প্রতিক্রিয়া আউটপুট প্রবাহে ফাইল সামগ্রী লিখুন।attachment
সর্বাধিক গুরুত্বপূর্ণ অংশটি FacesContext#responseComplete()
জেএসএফকে জানাতে ফোন করা হয়েছে যে আপনি প্রতিক্রিয়াতে ফাইলটি লিখে দেওয়ার পরে এটি নেভিগেশন এবং রেন্ডারিং করা উচিত নয়, অন্যথায় প্রতিক্রিয়াটির শেষ পৃষ্ঠার এইচটিএমএল সামগ্রী বা পুরানো জেএসএফ সংস্করণগুলিতে দূষিত হয়ে যাবে , আপনি যখন জেএসএফ বাস্তবায়ন এইচটিএমএল রেন্ডার করার জন্য কল করেন তখন আপনি IllegalStateException
একটি বার্তা সহ একটি পাবেন ।getoutputstream() has already been called for this response
getWriter()
এজ্যাক্স বন্ধ করুন / রিমোট কমান্ড ব্যবহার করবেন না!
আপনি শুধুমাত্র নিশ্চিত যে কর্ম পদ্ধতি করতে হবে না একটি AJAX অনুরোধ ডাকা, কিন্তু এটা একটি স্বাভাবিক অনুরোধ ডাকা করছেন যে শুধু আগুন <h:commandLink>
এবং <h:commandButton>
। অ্যাজাক্স অনুরোধগুলি এবং রিমোট কমান্ডগুলি জাভাস্ক্রিপ্ট দ্বারা পরিচালিত হয় যা সুরক্ষার কারণে, এজ্যাক্স প্রতিক্রিয়াটির বিষয়বস্তুর সাথে কথোপকথন হিসাবে সংরক্ষণের জন্য বাধ্য করার মতো কোনও সুবিধা নেই ।
আপনি যদি উদাহরণস্বরূপ প্রাইমফ্রিজ ব্যবহার করছেন <p:commandXxx>
তবে আপনাকে অবশ্যই নিশ্চিত করতে হবে যে আপনি স্পষ্টরূপে ajax="false"
অ্যাট্রিবিটের মাধ্যমে এজাক্স বন্ধ করে দিয়েছেন। আপনি যদি আইসিইফেস ব্যবহার করছেন <f:ajax disabled="true" />
তবে কমান্ড উপাদানটিতে আপনাকে বাসা বাঁধতে হবে ।
জেনেরিক জেএসএফ 2.x উদাহরণ
public void download() throws IOException {
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
ec.responseReset();
ec.setResponseContentType(contentType);
ec.setResponseContentLength(contentLength);
ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
OutputStream output = ec.getResponseOutputStream();
fc.responseComplete();
}
জেনেরিক জেএসএফ 1.x উদাহরণ
public void download() throws IOException {
FacesContext fc = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) fc.getExternalContext().getResponse();
response.reset();
response.setContentType(contentType);
response.setContentLength(contentLength);
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
OutputStream output = response.getOutputStream();
fc.responseComplete();
}
সাধারণ স্ট্যাটিক ফাইল উদাহরণ
স্থানীয় ডিস্ক ফাইল সিস্টেম থেকে আপনার যদি কোনও স্ট্যাটিক ফাইল প্রবাহিত করতে হয় তবে নীচের মত কোডটি বিকল্পে রাখুন:
File file = new File("/path/to/file.ext");
String fileName = file.getName();
String contentType = ec.getMimeType(fileName); // JSF 1.x: ((ServletContext) ec.getContext()).getMimeType(fileName);
int contentLength = (int) file.length();
// ...
Files.copy(file.toPath(), output);
সাধারণ গতিশীল ফাইল উদাহরণ
যদি আপনাকে গতিশীলভাবে উত্পন্ন ফাইল যেমন পিডিএফ বা এক্সএলএস স্ট্রিমের দরকার হয় তবে কেবল output
সেখানে সরবরাহ করতে হবে যেখানে ব্যবহৃত এপিআই এর প্রত্যাশা করে OutputStream
।
যেমন আইটেক্সট পিডিএফ:
String fileName = "dynamic.pdf";
String contentType = "application/pdf";
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, output);
document.open();
document.close();
উদাঃ অ্যাপাচি পিওআই এইচএসএসএফ:
String fileName = "dynamic.xls";
String contentType = "application/vnd.ms-excel";
HSSFWorkbook workbook = new HSSFWorkbook();
workbook.write(output);
workbook.close();
মনে রাখবেন আপনি এখানে সামগ্রীর দৈর্ঘ্য সেট করতে পারবেন না। সুতরাং প্রতিক্রিয়া সামগ্রীর দৈর্ঘ্য সেট করতে আপনাকে লাইনটি সরিয়ে ফেলতে হবে। এটি প্রযুক্তিগতভাবে কোনও সমস্যা নয়, একমাত্র অসুবিধাটি হ'ল এন্ডুয়েসারকে একটি অজানা ডাউনলোড অগ্রগতি উপস্থাপন করা হবে। যদি এটি গুরুত্বপূর্ণ হয় তবে আপনাকে প্রথমে একটি স্থানীয় (অস্থায়ী) ফাইল লিখতে হবে এবং তারপরে এটি পূর্ববর্তী অধ্যায়ে বর্ণিতভাবে সরবরাহ করতে হবে।
ইউটিলিটি পদ্ধতি
আপনি JSF ইউটিলিটি লাইব্রেরি ব্যবহার করেন, তাহলে OmniFaces , তাহলে আপনি তিনটি সুবিধাজনক একটি ব্যবহার করতে পারেন Faces#sendFile()
হয় একটি গ্রহণ পদ্ধতি File
, অথবা একটি InputStream
, অথবা একটি byte[]
, এবং উল্লেখ কিনা ফাইল একটি সংযুক্তি (যেমন ডাউনলোড করা উচিত true
) অথবা ইনলাইন ( false
)।
public void download() throws IOException {
Faces.sendFile(file, true);
}
হ্যাঁ, এই কোডটি যেমন রয়েছে তেমন সম্পূর্ণ। আপনার responseComplete()
নিজের উপর অনুরোধ করার প্রয়োজন নেই । এই পদ্ধতিটি আইই-নির্দিষ্ট হেডারের সাথে এবং ইউটিএফ -8 ফাইলের নামগুলিও যথাযথভাবে ডিল করে। আপনি এখানে সোর্স কোড খুঁজে পেতে পারেন ।
InputStream
জন্য পরিকাঠামোp:fileDownload
, এবং আমি রূপান্তর করতে কিভাবে পরিচালিত করেন নিOutputStream
করারInputStream
। এখন এটি পরিষ্কার হয়ে গেছে যে এমনকি কোনও অ্যাকশন শ্রোতা প্রতিক্রিয়া সামগ্রীটির ধরন পরিবর্তন করতে পারে এবং তারপরে প্রতিক্রিয়াটিকে কোনওভাবেই ব্যবহারকারী-এজেন্টের পক্ষ থেকে ফাইল ডাউনলোড হিসাবে সম্মান করা হবে। ধন্যবাদ!