জাভা ওয়েব অ্যাপ্লিকেশনটিতে অ্যাপ্লিকেশন সার্ভারের বাইরে থেকে স্থিতিশীল ডেটা পরিবেশন করার সহজ উপায়


131

আমার একটি জাভা ওয়েব অ্যাপ্লিকেশন টমক্যাটে চলছে। আমি স্থিতিশীল চিত্রগুলি লোড করতে চাই যা ওয়েব ইউআই এবং অ্যাপ্লিকেশন দ্বারা উত্পন্ন পিডিএফ ফাইলগুলিতে উভয়ই প্রদর্শিত হবে। এছাড়াও ওয়েব ইউআইয়ের মাধ্যমে আপলোড করে নতুন চিত্র যুক্ত করা এবং সংরক্ষণ করা হবে।

ওয়েব ধারক মধ্যে স্ট্যাটিক ডেটা সংরক্ষণ করে এটি করা সমস্যা নয় তবে ওয়েব ধারকটির বাইরে থেকে এগুলি সংরক্ষণ এবং লোড করা আমার মাথা ব্যথা করে।

আমি এই স্থানে স্থির ডেটা পরিবেশন করার জন্য অ্যাপাচি এর মতো আলাদা একটি ওয়েব সার্ভার ব্যবহার না করা পছন্দ করব। আমি একটি ডাটাবেসে বাইনারি মধ্যে ছবি সংরক্ষণ করার ধারণা পছন্দ করি না।

আমি ইমেজ ডিরেক্টরিটি ওয়েব ধারকটির বাইরে কোনও ডিরেক্টরিকে নির্দেশ করে এমন একটি প্রতীকী লিঙ্ক হওয়ার মতো কিছু পরামর্শ দেখেছি, তবে এই পদ্ধতিটি কি উইন্ডোজ এবং * নিক্স পরিবেশ উভয় ক্ষেত্রেই কাজ করবে?

কেউ কেউ ইমেজ পরিবেশন করার জন্য ফিল্টার বা সার্লেট লেখার পরামর্শ দেয় তবে কীভাবে এটি সম্পাদন করা যায় সে সম্পর্কে আরও বিস্তারিত তথ্যের দিকে বিন্দু বিনীত সে পরামর্শগুলি খুব অস্পষ্ট এবং উচ্চ-স্তরের ছিল।

উত্তর:


161

আমি ইমেজ ডিরেক্টরিটি ওয়েব ধারকটির বাইরে কোনও ডিরেক্টরিকে নির্দেশ করে এমন একটি প্রতীকী লিঙ্ক হওয়ার মতো কিছু পরামর্শ দেখেছি, তবে এই পদ্ধতিটি কি উইন্ডোজ এবং * নিক্স পরিবেশ উভয় ক্ষেত্রেই কাজ করবে?

যদি আপনি * নিক্স ফাইল সিস্টেমের পাথের নিয়মগুলি মেনে চলেন (উদাহরণস্বরূপ আপনি যেমন হিসাবে একচেটিয়াভাবে ফরোয়ার্ড স্ল্যাশ ব্যবহার করেন /path/to/files), তবে এটি উইন্ডোতে পাশাপাশি কুৎসিত File.separatorস্ট্রিং-কনটেন্টেশনগুলির সাথে চারপাশে ঝাঁকুনির প্রয়োজন ছাড়াই কাজ করবে । এটি কেবল একই ওয়ার্কিং ডিস্কে স্ক্যান করা হবে যেখানে এই আদেশটি চাওয়া হয়েছে। সুতরাং যদি টমকেট উদাহরণস্বরূপ ইনস্টল করা থাকে C:তবে /path/to/filesপ্রকৃতপক্ষে এটি নির্দেশ করবে C:\path\to\files

যদি ফাইলগুলি সমস্ত ওয়েবপ্যাপের বাইরে থাকে এবং আপনি টমক্যাটগুলি DefaultServletসেগুলি পরিচালনা করতে চান তবে মূলত টমকেটে আপনাকে যা করতে হবে তা হ'ল নীচের প্রসঙ্গ উপাদানটি /conf/server.xmlঅভ্যন্তরীণ <Host>ট্যাগে যুক্ত করা:

<Context docBase="/path/to/files" path="/files" />

এইভাবে তারা মাধ্যমে অ্যাক্সেসযোগ্য হবে http://example.com/files/...। গ্লাস ফিশ / পেয়ারা কনফিগারেশন উদাহরণটি এখানে পাওয়া যাবে এবং ওয়াইল্ডফ্লাই কনফিগারেশন উদাহরণটি এখানে পাওয়া যাবে

আপনি পড়া / লেখা ফাইল নিজেকে নিয়ন্ত্রণ করতে চান, তাহলে আপনি একটি তৈরি করতে হবে Servletএই যা মূলত শুধু একটি পায় জন্য InputStreamউদাহরণস্বরূপ গন্ধ মধ্যে ফাইলের FileInputStreamএবং এটি লিখেছেন OutputStreamএর HttpServletResponse

প্রতিক্রিয়ায়, আপনার Content-Typeশিরোনাম সেট করা উচিত যাতে ক্লায়েন্ট জানে যে সরবরাহিত ফাইলটির সাথে কোন অ্যাপ্লিকেশনটি সংযুক্ত করতে হবে। এবং, আপনার শিরোনামটি সেট করা উচিত Content-Lengthযাতে ক্লায়েন্টটি ডাউনলোডের অগ্রগতি গণনা করতে পারে, অন্যথায় এটি অজানা। এবং, আপনি যেমন সংরক্ষণ করুন ডায়ালগ চান তবে আপনাকে এই Content-Dispositionশিরোনামটি সেট করা উচিত , অন্যথায় ক্লায়েন্ট এটিকে ইনলাইন প্রদর্শনের চেষ্টা করবে। পরিশেষে কেবল প্রতিক্রিয়া আউটপুট প্রবাহে ফাইল সামগ্রী লিখুন।attachment

এই জাতীয় সার্লেটের একটি প্রাথমিক উদাহরণ:

@WebServlet("/files/*")
public class FileServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
    {
        String filename = URLDecoder.decode(request.getPathInfo().substring(1), "UTF-8");
        File file = new File("/path/to/files", filename);
        response.setHeader("Content-Type", getServletContext().getMimeType(filename));
        response.setHeader("Content-Length", String.valueOf(file.length()));
        response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
        Files.copy(file.toPath(), response.getOutputStream());
    }

}

url-patternউদাহরণস্বরূপ কোনওটিতে ম্যাপ করা হলে /files/*, আপনি এটি দ্বারা কল করতে পারেন http://example.com/files/image.pngDefaultServletডিফল্ট চিত্র সরবরাহ করা (যেমন if (!file.exists()) file = new File("/path/to/files", "404.gif")বা তাই) এর চেয়ে অনুরোধগুলির উপর আপনার আরও নিয়ন্ত্রণ থাকতে পারে । এছাড়াও ব্যবহার request.getPathInfo()করা হয় উপরে অগ্রাধিকার request.getParameter()কারণ এটির আরও বেশি এসইও বন্ধুত্বপূর্ণ এবং অন্যথায় ইন্টারনেট সময় সঠিক ফাইলের নাম বাছাই করা হবে না এই রূপে সংরক্ষণ করুন

আপনি ডাটাবেস থেকে ফাইল পরিবেশন করার জন্য একই যুক্তি পুনরায় ব্যবহার করতে পারেন। সহজভাবে new FileInputStream()দ্বারা প্রতিস্থাপন ResultSet#getInputStream()

আশাকরি এটা সাহায্য করবে.

আরো দেখুন:


1
@ স্যালুটন মন্ডো: সর্বনিম্ন প্রচেষ্টা নিয়ে উপায়।
বালুসসি

@ বালাসসি, আমি এটি চেষ্টা করেছি: <Context docBase="/path/to/images" path="/images" />উইন্ডোজে, তবে ওয়েব অ্যাপস ফোল্ডারের সাথে সম্পর্কিত পথ পাচ্ছি :C:\install\apache-tomcat-8.0.26\webapps\tmp] is not valid
এসিভি

উইন্ডোজে এটি হওয়া উচিত:<Context docBase="C:\tmp\" path="/images" />
ACV

এবং করার HTTP Status 404 - /images/সময় পেয়ে যাচ্ছেন http://localhost:8080/images/:, কিন্তু tmpকাজগুলির অধীনে একটি নির্দিষ্ট ফাইল করুন : http://localhost:8080/images/Tulips.jpgঠিক আছে
এসিভি

এইভাবে যদি আমি ফোল্ডারের ভিতরে কোনও চিত্র রাখি তবে আপনি সার্ভারটি পুনরায় চালু না করলে চিত্রটির লিঙ্কটি প্রতিক্রিয়া দেবে 404, এর কোনও কারণ আছে কি?
ম্যাটিউস ভিকারি

9

আপনি আপনার চিত্রগুলি একটি নির্দিষ্ট পথে রাখার মাধ্যমে এটি করতে পারেন (উদাহরণস্বরূপ: / var / চিত্রসমূহ, বা সি: \ চিত্রগুলি), আপনার অ্যাপ্লিকেশন সেটিংসে একটি সেটিংস যুক্ত করুন (সেটিংস.class দ্বারা আমার উদাহরণে উপস্থাপিত), এবং সেগুলি লোড করুন আপনার মত একটি মত HttpServlet:

String filename = Settings.getValue("images.path") + request.getParameter("imageName")
FileInputStream fis = new FileInputStream(filename);

int b = 0;
while ((b = fis.read()) != -1) {
        response.getOutputStream().write(b);
}

অথবা আপনি যদি চিত্রটি পরিচালনা করতে চান:

String filename = Settings.getValue("images.path") + request.getParameter("imageName")
File imageFile = new File(filename);
BufferedImage image = ImageIO.read(imageFile);
ImageIO.write(image, "image/png", response.getOutputStream());

তাহলে এইচটিএমএল কোড হবে would <img src="imageServlet?imageName=myimage.png" />

অবশ্যই আপনার বিভিন্ন সামগ্রীর ধরণের সেবা দেওয়ার কথা ভাবা উচিত - "চিত্র / জেপিইগ", উদাহরণস্বরূপ ফাইল এক্সটেনশনের উপর ভিত্তি করে। এছাড়াও আপনি কিছু ক্যাচিং প্রদান করা উচিত।

এছাড়াও আপনি এই চিত্রটি গুণমান পুনরুদ্ধারের জন্য, যুক্তি হিসাবে প্রস্থ এবং উচ্চতা পরামিতি সরবরাহ করে এবং ব্যবহার করে image.getScaledInstance(w, h, Image.SCALE_SMOOTH) অবশ্যই পারফরম্যান্স বিবেচনা করে ব্যবহার করতে পারেন ।


2
এর জন্য আপনার সত্যিই জাভা 2 ডি এপিআইয়ের দরকার নেই, এটি কেবল অযথাই আরও ওভারহেড যুক্ত করবে। কেবল একটি ইনপুটস্ট্রিম পড়ুন এবং আউটপুট স্ট্রিমে লিখুন।
বালুসসি

1
হ্যাঁ, আমি উদ্ধার এবং অন্যান্য কারসাজির ধারণা দিয়ে প্রতিক্রিয়া শুরু করেছি, তবে এটি সহজ করেই শেষ করেছি।
বোঝো

7

সার্ভারে যোগ করুন। এক্সএমএল:

 <Context docBase="c:/dirtoshare" path="/dir" />

ওয়েব.এক্সএমএলগুলিতে দির ফাইল তালিকা পরামিতি সক্ষম করুন:

    <init-param>
        <param-name>listings</param-name>
        <param-value>true</param-value>
    </init-param>

ওয়েব.এক্সএমএল পরিবর্তনের সাথে সাথে ফাইলগুলি বাছাই করার জন্য ফাইলগুলির একটি তালিকা পেতে পারি?
টমাসজ ওয়াজকিজেক

1
এই পরিবর্তনটি টমকটের ওয়েব.এক্সএমএল এ হবে, আপনার আবেদন নয়
vsingh

এর জন্য ধন্যবাদ! ওয়েব.এক্সএমএল-তে ডায়ার ফাইল তালিকা পরামিতি সক্ষম করা কি প্রয়োজনীয়?
dariru

6

প্রয়োজনীয়তা: WEBROOT ডিরেক্টরি থেকে বা স্থানীয় ডিস্ক থেকে স্থিতিশীল সংস্থান (চিত্র / ভিডিও ইত্যাদি etc.) অ্যাক্সেস করা হচ্ছে

পদক্ষেপ 1:
টমক্যাট সার্ভারের ওয়েব অ্যাপসের আওতায় একটি ফোল্ডার তৈরি করুন,

পদক্ষেপ 2:
মাইপ্রোজের অধীনে একটি ওয়েব-আইএনএফ ফোল্ডার তৈরি করুন এটি একটি সাধারণ ওয়েব.এক্সএমএল তৈরি করুন

ওয়েব.এক্সএমএল এর অধীনে কোড

<web-app>
</web-app>

উপরোক্ত দুটি পদক্ষেপের জন্য ডিরেক্টরি কাঠামো

c:\programfile\apachesoftwarefoundation\tomcat\...\webapps
                                                            |
                                                            |---myproj
                                                            |   |
                                                            |   |---WEB-INF
                                                                |   |
                                                                    |---web.xml

পদক্ষেপ 3:
এখন নীচের অবস্থানের অধীনে myproj.xML নামের একটি এক্সএমএল ফাইল তৈরি করুন

c:\programfile\apachesoftwarefoundation\tomcat\conf\catalina\localhost

মাইপ্রোজ.এক্সএমএল-এ কোড:

<Context path="/myproj/images" docBase="e:/myproj/" crossContext="false" debug="0" reloadable="true" privileged="true" /> 

পদক্ষেপ 4:
4 এ) এখন আপনার হার্ড ডিস্কের ই ড্রাইভে মাইপ্রোজ নামের একটি ফোল্ডার তৈরি করুন এবং একটি নতুন তৈরি করুন

নাম ইমেজ সহ ফোল্ডার এবং ইমেজ ফোল্ডারে কিছু চিত্র স্থাপন (e:myproj\images\)

ধরা যাক myfoto.jpg এর নীচে স্থাপন করা হয়েছে e:\myproj\images\myfoto.jpg

4 খ) এখন WEB-INF নামে একটি ফোল্ডার e:\myproj\WEB-INFতৈরি করুন এবং ওয়েব-INF ফোল্ডারে একটি ওয়েব.এক্সএমএল তৈরি করুন

ওয়েব.এক্সএমএলে কোড

<web-app>
</web-app>

পদক্ষেপ 5:
এখন সূচিপত্রের নাম। Html সহ একটি এইচটিএমএল ডকুমেন্ট তৈরি করুন এবং ই: \ মাইপ্রোজের নীচে রাখুন

সূচকের অধীনে CODE মাইপ্রোজে আপনাকে স্বাগতম

উপরের ধাপ 4 এবং 5 ধাপের ডিরেক্টরি কাঠামোটি নিম্নরূপ

E:\myproj
    |--index.html
    |
    |--images
    |     |----myfoto.jpg
    |
    |--WEB-INF
    |     |--web.xml

পদক্ষেপ::
এখন অ্যাপাচি টমক্যাট সার্ভারটি শুরু করুন

পদক্ষেপ::
ব্রাউজারটি খুলুন এবং নীচে ইউআরএল টাইপ করুন

http://localhost:8080/myproj    

তারপরে আপনি সূচিপত্র html এ সরবরাহ করা সামগ্রীটি প্রদর্শন করুন

পদক্ষেপ 8:
আপনার স্থানীয় হার্ড ডিস্কের অধীনে চিত্রগুলি অ্যাক্সেস করতে (ওয়েবরূটের বাইরে)

http://localhost:8080/myproj/images/myfoto.jpg

আপনি কি দয়া করে আমাকে পরামর্শ দিতে পারেন, কীভাবে গতিশীল মানগুলির জন্য একই জিনিস করতে হয়। আমি বলতে চাই যে আমি আমার স্থানীয় ডিরেক্টরিতে ডেটা (এক্সএমএল) লিখতে চাইছি এবং এবং এটি আমার জেএসপি পৃষ্ঠায় পড়তে চাই। ডিরেক্টরিতে পরিচালিত সার্ভারে লেখার কোনও উপায় কি আমি উপরের পদ্ধতিটি ব্যবহার করে সেগুলিতে অ্যাক্সেস করতে পারি ??
সুদীপ 7


আমার ভুল পোস্টটি ঠিকঠাক কাজ করছে আমি ঠিক ই / / মাইপ্রোজ / এর শেষে / লিখতে ভুলে গেছি এটি ই: / মাইপ্রোজে / এবং এটির কাজটি সূক্ষ্ম ধন্যবাদ @ এসবাবামকা
রোজারওয়ার

হাই, পোস্টের জন্য ধন্যবাদ এবং এটি খুব দরকারী। এখানে আমি সেই নির্দিষ্ট ডিরেক্টরিটিতে ইন্টারফেসের মাধ্যমে ফাইলগুলি আপলোড করতে চাই। আমি তার জন্য POST পদ্ধতি সক্ষম করতে চাই। যে কেউ দয়া করে আমাকে একইভাবে সহায়তা করতে পারেন।
ভিকি

6

এটি আমার কর্মক্ষেত্রের গল্প:
- আমরা বহুগুণ চিত্রগুলি এবং ডকুমেন্ট ফাইলগুলি স্ট্রুট 1 এবং টমক্যাট 7.x ব্যবহার করে আপলোড করার চেষ্টা করি।
- আমরা ফাইল সিস্টেম, ফাইলের নাম এবং ডাটাবেস রেকর্ডের পুরো পথে আপলোড করা ফাইলগুলি লেখার চেষ্টা করি।
- আমরা ওয়েব অ্যাপ্লিকেশন ডিরেক্টরি বাইরে ফাইল ফোল্ডার পৃথক করার চেষ্টা করি । (*)

নীচের সমাধানটি বেশ সহজ, প্রয়োজনীয়তার জন্য কার্যকর (*):

META-INF/context.xmlনিম্নলিখিত বিষয়বস্তু সহ ফাইল ফাইল: (উদাহরণস্বরূপ, আমার অ্যাপ্লিকেশন চালানো হয় http://localhost:8080/ABC, আমার অ্যাপ্লিকেশন / প্রকল্পের নাম দেওয়া হয়েছে ABC)। (এটিও ফাইলের সম্পূর্ণ বিষয়বস্তু context.xml)

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/ABC" aliases="/images=D:\images,/docs=D:\docs"/>

(টমকেট সংস্করণ 7 বা তার পরে কাজ করে)

ফলাফল: আমাদের 2 টি ওরফে তৈরি করা হয়েছে। উদাহরণস্বরূপ, আমরা এখানে চিত্রগুলি সংরক্ষণ করি: D:\images\foo.jpg এবং লিঙ্ক থেকে বা চিত্র ট্যাগ ব্যবহার করে দেখুন:

<img src="http://localhost:8080/ABC/images/foo.jsp" alt="Foo" height="142" width="142">

অথবা

<img src="/images/foo.jsp" alt="Foo" height="142" width="142">

(আমি নেটবিন 7..x ব্যবহার করি, নেটবিনগুলি স্বয়ংক্রিয় ফাইল তৈরি করে বলে মনে হয় WEB-INF\context.xml)


2

আপনাকে প্রেরণ সিদ্ধান্ত নেন তাহলে FileServletতাহলে আপনি প্রয়োজন হবে allowLinking="true"মধ্যে context.xmlকরার অনুমতি অনুক্রমে FileServletsymlinks তর্ক করতে।

Http://tomcat.apache.org/tomcat-6.0-doc/config/context.html দেখুন


0

যদি কেউ গৃহীত উত্তর দিয়ে তার সমস্যা সমাধান করতে সক্ষম না হয় তবে নীচের বিবেচনাগুলিতে নোট করুন:

  1. বৈশিষ্ট্য localhost:<port>সহ উল্লেখ করার দরকার নেই <img> src
  2. নিশ্চিত হয়ে নিন যে আপনি এই প্রকল্পটিগ্রহণের বাইরে চালাচ্ছেন, কারণ গ্রহনটি context docBaseতার নিজের স্থানীয় server.xmlফাইলের ভিতরে এন্ট্রি তৈরি করে ।

0

কোনও ফাইলের ইনপুট স্ট্রিমটি পড়ুন এবং ServletOutputStreamক্লায়েন্টকে বাইনারি ডেটা প্রেরণের জন্য এটি লিখুন ।

@WebServlet("/files/URLStream")
public class URLStream extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public URLStream() {
        super();
    }

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        File source = new File("D:\\SVN_Commit.PNG");
        long start = System.nanoTime();

        InputStream image = new FileInputStream(source);

        /*String fileID = request.getParameter("id");
        System.out.println("Requested File ID : "+fileID);
        // Mongo DB GridFS - https://stackoverflow.com/a/33544285/5081877
        image = outputImageFile.getInputStream();*/

        if( image != null ) {
            BufferedInputStream bin = null;
            BufferedOutputStream bout = null;
            ServletOutputStream sos = response.getOutputStream();
            try {
                bin = new BufferedInputStream( image );
                bout = new BufferedOutputStream( sos );
                int ch =0; ;
                while((ch=bin.read())!=-1) {
                    bout.write(ch);
                }
            } finally {
                bin.close();
                image.close();
                bout.close();
                sos.close();
            }

        } else {
            PrintWriter writer = response.getWriter();
            writer.append("Something went wrong with your request.");
            System.out.println("Image not available.");
        }
        System.out.println("Time taken by Stream Copy = "+(System.nanoTime()-start));
    }
}

URL টি srcattibute এ সরাসরি ফলাফল দিন ।

<img src='http://172.0.0.1:8080/ServletApp/files/URLStream?id=5a575be200c117cc2500003b' alt="mongodb File"/>
<img src='http://172.0.0.1:8080/ServletApp/files/URLStream' alt="local file"/>

<video controls="controls" src="http://172.0.0.1:8080/ServletApp/files/URLStream"></video>

0

আপনি যদি জ্যাক্স - আরএসের সাথে কাজ করতে চান (যেমন, RESTEasy) চেষ্টা করে দেখুন:

@Path("/pic")
public Response get(@QueryParam("url") final String url) {
    String picUrl = URLDecoder.decode(url, "UTF-8");

    return Response.ok(sendPicAsStream(picUrl))
            .header(HttpHeaders.CONTENT_TYPE, "image/jpg")
            .build();
}

private StreamingOutput sendPicAsStream(String picUrl) {
    return output -> {
        try (InputStream is = (new URL(picUrl)).openStream()) {
            ByteStreams.copy(is, output);
        }
    };
}

ব্যবহার javax.ws.rs.core.Responseএবংcom.google.common.io.ByteStreams


-1

আমি এটি আরও সহজ। সমস্যা: একটি সিএসএস ফাইলের img ফোল্ডারের url লিঙ্ক ছিল। পায় 404।

আমি url, http: // tomcatfolder: port / img / blablah.png এর দিকে তাকালাম , যার অস্তিত্ব নেই। তবে, এটি টমকেটের মূল অ্যাপটি নির্দেশ করে।

সুতরাং আমি কেবলমাত্র আমার ওয়েব অ্যাপ্লিকেশন থেকে img ফোল্ডারটি সেই রুট অ্যাপটিতে অনুলিপি করেছি। কাজ করে!

উত্পাদনের জন্য অবশ্যই প্রস্তাবিত নয়, তবে এটি একটি অভ্যন্তরীণ সরঞ্জাম দেব অ্যাপ্লিকেশানের জন্য।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.