ভূমিকা
ব্রাউজ করতে এবং আপলোডের জন্য একটি ফাইল নির্বাচন করতে আপনাকে <input type="file">
ফর্মটিতে একটি HTML ক্ষেত্র প্রয়োজন । এইচটিএমএল স্পেসিফিকেশনে বর্ণিত হিসাবে আপনাকে POST
পদ্ধতিটি ব্যবহার enctype
করতে হবে এবং ফর্মটির বৈশিষ্ট্যটি সেট করতে হবে "multipart/form-data"
।
<form action="upload" method="post" enctype="multipart/form-data">
<input type="text" name="description" />
<input type="file" name="file" />
<input type="submit" />
</form>
এই জাতীয় ফর্ম জমা দেওয়ার পরে, বাইনারি মাল্টিপার্ট ফর্ম ডেটা অনুরোধের বডিটিতে একটি ভিন্ন ফর্ম্যাটে উপলব্ধenctype
সেট না থাকা চেয়ে ।
সার্লেলেট 3.0.০ এর আগে সার্ভলেট এপিআই স্থানীয়ভাবে সমর্থন করে নি multipart/form-data
। এটি কেবলমাত্র ডিফল্ট ফর্ম এনকটাইপ সমর্থন করে application/x-www-form-urlencoded
। request.getParameter()
এবং স্ত্রীদেরকে সব ফিরে আসবে null
যখন একাধিক ফর্ম তথ্য ব্যবহার করে। এখানেই সুপরিচিত অ্যাপাচি কমন্স ফাইলআপলোড ছবিতে এসেছিল।
ম্যানুয়ালি এটি বিশ্লেষণ করবেন না!
আপনি তত্ত্বগতভাবে অনুরোধের বডিটি নিজের উপর ভিত্তি করে বিশ্লেষণ করতে পারেন ServletRequest#getInputStream()
। তবে এটি একটি সুনির্দিষ্ট এবং ক্লান্তিকর কাজ যার জন্য আরএফসি 2388 সম্পর্কে সুনির্দিষ্ট জ্ঞানের প্রয়োজন । আপনার নিজের এটি করার চেষ্টা করা উচিত নয় বা ইন্টারনেটে অন্য কোথাও পাওয়া কিছু হোমগ্রাউন লাইব্রেরি-কম কোড কপিপেষ্ট করা উচিত নয়। অনেকগুলি অনলাইন উত্স এতে সফলভাবে ব্যর্থ হয়েছে, যেমন রোজিন্ডিয়া ডটনেট। আরো দেখুনপিডিএফ ফাইল আপলোডও । আপনার বরং সত্যিকারের একটি লাইব্রেরি ব্যবহার করা উচিত যা কয়েক বছর ধরে কয়েক মিলিয়ন ব্যবহারকারীর দ্বারা ব্যবহৃত হয় (এবং স্পষ্টভাবে পরীক্ষিত!)। এই জাতীয় গ্রন্থাগারটি তার দৃust়তা প্রমাণ করেছে।
আপনি ইতিমধ্যে সার্লেট ৩.০ বা আরও নতুনতে থাকলে নেটিভ API ব্যবহার করুন
যদি আপনি কমপক্ষে servlet 3.0 (টমক্যাট 7, জেটি 9, জবস এএস 6, গ্লাস ফিশ 3, ইত্যাদি) ব্যবহার করে থাকেন তবে HttpServletRequest#getPart()
স্বতন্ত্র মাল্টিপার্ট ফর্ম ডেটা আইটেম সংগ্রহ করার জন্য আপনি সরবরাহকৃত স্ট্যান্ডার্ড এপিআই ব্যবহার করতে পারেন (বেশিরভাগ সার্লেলেট 3.0 বাস্তবায়নগুলি অ্যাপাচি ব্যবহার করে এই জন্য কভারস কমন্স ফাইল আপলোড!)। এছাড়াও, সাধারণ ফর্ম ক্ষেত্রগুলি দ্বারা উপলব্ধgetParameter()
সাধারণ উপায়ে উপলব্ধ।
প্রথমে আপনার সার্লেলেটটিকে @MultipartConfig
এটির multipart/form-data
অনুরোধগুলি সনাক্ত এবং সমর্থন করার জন্য এনেটেট করুন এবং এভাবে getPart()
কাজ শুরু করুন:
@WebServlet("/upload")
@MultipartConfig
public class UploadServlet extends HttpServlet {
// ...
}
তারপরে, এটি doPost()
নিম্নলিখিত হিসাবে বাস্তবায়ন করুন :
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String description = request.getParameter("description"); // Retrieves <input type="text" name="description">
Part filePart = request.getPart("file"); // Retrieves <input type="file" name="file">
String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
InputStream fileContent = filePart.getInputStream();
// ... (do your job here)
}
নোট করুন Path#getFileName()
। ফাইলের নাম পাওয়ার ক্ষেত্রে এটি একটি এমএসআইই ফিক্স। এই ব্রাউজারটি ভুলভাবে কেবল ফাইল নামের পরিবর্তে নামের সাথে পুরো ফাইল পাঠায়।
আপনার যদি <input type="file" name="file" multiple="true" />
মাল্টি-ফাইল আপলোডের জন্য থাকে তবে সেগুলি নীচে হিসাবে সংগ্রহ করুন (দুর্ভাগ্যক্রমে এমন কোনও পদ্ধতি নেই request.getParts("file")
):
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// ...
List<Part> fileParts = request.getParts().stream().filter(part -> "file".equals(part.getName()) && part.getSize() > 0).collect(Collectors.toList()); // Retrieves <input type="file" name="file" multiple="true">
for (Part filePart : fileParts) {
String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
InputStream fileContent = filePart.getInputStream();
// ... (do your job here)
}
}
আপনি যখন সার্লেট ৩.১ এ নেই, ম্যানুয়ালি ফাইলের নাম জমা দিন
Part#getSubmittedFileName()
টীকাট 8, জেটি 9, ওয়াইল্ডফ্লাই 8, গ্লাস ফিশ 4 ইত্যাদি সার্ভলেট 3.1-এ প্রবর্তিত হয়েছে তা নোট করুন । আপনি যদি এখনও সার্লেট ৩.১ এ নেই তবে জমা দেওয়া ফাইলের নামটি পেতে আপনার অতিরিক্ত ইউটিলিটি পদ্ধতি প্রয়োজন need
private static String getSubmittedFileName(Part part) {
for (String cd : part.getHeader("content-disposition").split(";")) {
if (cd.trim().startsWith("filename")) {
String fileName = cd.substring(cd.indexOf('=') + 1).trim().replace("\"", "");
return fileName.substring(fileName.lastIndexOf('/') + 1).substring(fileName.lastIndexOf('\\') + 1); // MSIE fix.
}
}
return null;
}
String fileName = getSubmittedFileName(filePart);
ফাইলের নাম পাওয়ার ক্ষেত্রে এমএসআইই ফিক্সটি নোট করুন। এই ব্রাউজারটি ভুলভাবে কেবল ফাইল নামের পরিবর্তে নামের সাথে পুরো ফাইল পাঠায়।
আপনি এখনও সার্লেট ৩.০-তে নেই, তখন অ্যাপাচি কমন্স ফাইলআপলোড ব্যবহার করুন
আপনি যদি এখনও সার্লেট ৩.০-তে নেই (এটি আপগ্রেড হওয়ার সময় সম্পর্কে নয়?), সাধারণ অনুশীলনটি হ'ল মাল্টিপার্ট ফর্ম ডেটা অনুরোধগুলি পার্স করার জন্য অ্যাপাচি কমন্স ফাইলআপলোড ব্যবহার করা । এটিতে একটি দুর্দান্ত ইউজার গাইড এবং এফএকিউ রয়েছে (সাবধানে উভয়টি দিয়ে যান)। ও'রিলি (" কোস " )ও রয়েছেMultipartRequest
, তবে এটিতে কিছু (গৌণ) বাগ রয়েছে এবং কয়েক বছর ধরে সক্রিয়ভাবে আর রক্ষণাবেক্ষণ করা হচ্ছে না। আমি এটি ব্যবহার করার পরামর্শ দেব না। অ্যাপাচি কমন্স ফাইলআপলোড এখনও সক্রিয়ভাবে রক্ষণাবেক্ষণ করা হয় এবং বর্তমানে খুব পরিপক্ক।
অ্যাপাচি কমন্স ফাইলআপলোড ব্যবহার করতে আপনার ওয়েব অ্যাপ্লিকেশনগুলিতে কমপক্ষে নিম্নলিখিত ফাইল থাকা দরকার /WEB-INF/lib
:
আপনার প্রাথমিক প্রচেষ্টাটি সম্ভবত ব্যর্থ হয়েছে কারণ আপনি কমন্স আইওকে ভুলে গেছেন।
অ্যাপাচি কমন্স ফাইলআপলোড ব্যবহার করার doPost()
সময় আপনার UploadServlet
চেহারাটি কেমন দেখতে পারে তা এখানে একটি উদাহরণ :
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
for (FileItem item : items) {
if (item.isFormField()) {
// Process regular form field (input type="text|radio|checkbox|etc", select, etc).
String fieldName = item.getFieldName();
String fieldValue = item.getString();
// ... (do your job here)
} else {
// Process form file field (input type="file").
String fieldName = item.getFieldName();
String fileName = FilenameUtils.getName(item.getName());
InputStream fileContent = item.getInputStream();
// ... (do your job here)
}
}
} catch (FileUploadException e) {
throw new ServletException("Cannot parse multipart request.", e);
}
// ...
}
এটা খুবই গুরুত্বপূর্ণ যে আপনি কল করি না getParameter()
, getParameterMap()
, getParameterValues()
, getInputStream()
, getReader()
একই অনুরোধ পূর্বেই উপর ইত্যাদি। অন্যথায় সার্লেট কন্টেইনারটি অনুরোধের বডিটি পড়বে এবং পার্স করবে এবং এভাবে অ্যাপাচি কমন্স ফাইলআপলোড একটি খালি অনুরোধের বডি পাবে। আরও দেখুন সার্ভলেট ফাইল আপলোড # পার্সেরউয়েস্ট (অনুরোধ) খালি তালিকা দেয় ।
নোট করুনFilenameUtils#getName()
। ফাইলের নাম পাওয়ার ক্ষেত্রে এটি একটি এমএসআইই ফিক্স। এই ব্রাউজারটি ভুলভাবে কেবল ফাইল নামের পরিবর্তে নামের সাথে পুরো ফাইল পাঠায়।
বিকল্পভাবে আপনি Filter
এগুলি সমস্ত এমনভাবে গুটিয়ে রাখতে পারেন যা এটি স্বয়ংক্রিয়ভাবে পার্স করে এবং স্টাফটিকে অনুরোধের প্যারামিটার্যাপে ফিরিয়ে দেয় যাতে আপনি request.getParameter()
স্বাভাবিক পদ্ধতিতে চালিয়ে যেতে পারেন এবং আপলোড করা ফাইলটি পুনরুদ্ধার করতে পারেন request.getAttribute()
। আপনি এই ব্লগ নিবন্ধে একটি উদাহরণ খুঁজে পেতে পারেন ।
গ্লাস ফিশ 3 বাগটি getParameter()
এখনও ফিরছে Worknull
নোট করুন যে 3.1.2 এর চেয়ে পুরানো গ্লাসফিশ সংস্করণগুলিতে একটি বাগ রয়েছে যার মধ্যে getParameter()
এখনও ফিরে আসে null
। আপনি যদি এই জাতীয় পাত্রে লক্ষ্য করে থাকেন এবং এটিকে আপগ্রেড করতে না পারেন তবে আপনাকে getPart()
এই ইউটিলিটি পদ্ধতির সাহায্যে মানটি বের করতে হবে :
private static String getValue(Part part) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(part.getInputStream(), "UTF-8"));
StringBuilder value = new StringBuilder();
char[] buffer = new char[1024];
for (int length = 0; (length = reader.read(buffer)) > 0;) {
value.append(buffer, 0, length);
}
return value.toString();
}
String description = getValue(request.getPart("description")); // Retrieves <input type="text" name="description">
আপলোড করা ফাইল সংরক্ষণ করা হচ্ছে (ব্যবহার করবেন getRealPath()
না part.write()
!)
প্রাপ্ত InputStream
(( fileContent
উপরের কোড স্নিপেটগুলিতে প্রদর্শিত ভেরিয়েবলটি) ডিস্ক বা ডাটাবেসে সঠিকভাবে সংরক্ষণ করার জন্য নীচের উত্তরের দিকে যান:
আপলোড করা ফাইল পরিবেশন করা হচ্ছে
ডিস্ক বা ডাটাবেস থেকে ক্লায়েন্টকে ফিরিয়ে দেওয়া সংরক্ষিত ফাইলটি সঠিকভাবে পরিবেশন করার বিষয়ে বিশদে নীচের উত্তরের দিকে যান:
ফর্মটি আজাক্সফায় করছে
Ajax (এবং jQuery) ব্যবহার করে কীভাবে আপলোড করবেন তা নিম্নলিখিত উত্তরগুলিতে যান। মনে রাখবেন যে ফর্ম ডেটা সংগ্রহ করার জন্য সার্লেট কোডটির জন্য এই পরিবর্তন করার দরকার নেই! আপনি যেভাবে প্রতিক্রিয়া দেখিয়েছেন সেভাবেই কেবল পরিবর্তন করা যেতে পারে তবে এটি বরং তুচ্ছ (অর্থাত্ জেএসপিতে ফরোয়ার্ড না করে, কেবল কিছু জেএসএন বা এক্সএমএল প্রিন্ট করুন বা এমনকি সরল পাঠ্য যা অ্যাজাক্স কলটির জন্য দায়ী স্ক্রিপ্টটি প্রত্যাশা করছে তার উপর নির্ভর করে) print
আশা করি এই সব সাহায্য করে :)