java / jsp الصورة تحميل. أين للحفاظ على ملفات الصور هذه؟

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

  •  23-08-2019
  •  | 
  •  

سؤال

أنا أكتب تطبيقا بسيطا يتيح لك تحميل الصور. بعد التحميل، يمكن للمستخدم تمييزها أو إزالتها.

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

أنا أستخدم Java / JSP (إطار خطوط خصيصا ولكن مشكلتي عامة).

سؤالي هو أين يمكنني الاحتفاظ بملفات الصور هذه بمجرد تحميلها؟

الآن لدي تطبيقان ويب منتشران على خادم Tomcat. تطبيق ويب رئيسي واحد وغير ذلك هو المكان الذي قمت بتحميل الصور فيه.

ولكن هذا لا يعمل لأنه لا أستطيع رؤية الصور التي تم تحميلها في التطبيق الرئيسي حتى أعيد نشرها / أعد تشغيل Tomcat.

يبدو أن Tomcat لا يختار الصور التي تم تحميلها حديثا تلقائيا.

هل لدى أي احد حلول؟

هذا مشروع بسيط، لذلك لا أريد تخزينها في قاعدة بيانات أو استخدام Apache للصور. هذا كل شيء معقد للغاية لهذا المشروع الصغير.

شكرا.

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

المحلول

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

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

نصائح أخرى

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

بالمناسبة، قد ترغب في النظر إلى هذا خيط stackoverflow, ، مناقشتها مؤخرا حيث تخزين الصور. قد لا يحل مشكلتك، بالتأكيد سوف يمنحك المزيد من الثقة على ما تفعله.

لقد حل هذا بطرق مختلفة.

أولا، الطريقة غير المحمولة، هي أن Glassfish (وأعتقد أن Tomcat أيضا) يتيح لك تعيين دليل خارجي في التسلسل الهرمي Webapps. هذا يعمل بشكل جيد حقا ويفعل بالضبط ما تريد. يتيح لك تخزين صورك في دليل خارجي بعيدا عن WebApp الخاص بك، ومع ذلك لا يزال يخدمها.

ومع ذلك، فإن هذه التقنية غير محمولة.

الطريق الذي قمت به هو من خلال إنشاء مرشح.

يمكنك وضع المرشح في مكان ما واضحا، ويقول "/ الصور".

ما يفعله المرشح هذا:

  • إنه يتحقق من الصورة (أو أي شيء، وهو يعمل مع أي مورد ثابت) في دليل خاص داخل WebApp. على سبيل المثال، سنستخدم عنوان URL "/ Webapp / Images".

  • إذا كان الملف غير موجود، فنحن نسخ الملف من موقعك الخارجي إلى المكان المناسب داخل WebApp. لذلك، دعنا نقول عنوان URL REQYEST هو "/IMAGES/BANNER.GIF". وأن ملفاتك يتم تخزينها على القرص في "/ الصفحة الرئيسية / التطبيق / الصور". لذلك، ملف المصدر لدينا هو "/ home/app/images/banner.gif". ثم نسخها إلى حيث نريدها في شجرة WebApp. نحن نستخدم "servletcontext.getrealpath" لهذا. لذلك، ستكون الوجهة "servletcontextext.get realpath (" / webapp / images / banner.gif "). فقط انسخ المصدر إلى الوجهة.

  • إذا كان الملف موجودا بالفعل، أو الآن، فقم الآن بإعادة توجيه الصورة الفعلية إلى /webapp/images/banner.gif.

بفعالية في نهاية المطاف وجود ذاكرة التخزين المؤقت للملف داخل شجرة نشر WebApps. الجانب السفلي هو أنه ذاكرة تخزين مؤقت، لذلك يجب الحفاظ عليه (أي يجب عليك التحقق مما إذا كان الأصلي أحدث من ذاكرة التخزين المؤقت الخاصة بك، تأكد من حذفه إذا تم حذف المصدر، إلخ). أيضا، يكرر مواردك، لذلك ستستأك صورك، في النهاية، ضعف مساحة القرص. أخيرا، هناك تكلفة النسخ الأولي عند بدء التشغيل.

ومع ذلك، فإنه يعمل، ويمنعك من الاضطرار إلى خدمة الموارد الثابتة باستخدام التعليمات البرمجية الخاصة بك. (وهو الحل الثالث، قم بتعيين عامل تصفية / Servlet لاعتراض عناوين URL ويتفقه ببساطة بنفسك)

أود أن أنظر إلى البنية داخل Tomcat (على افتراض أنه موجود) للقيام بالتعيين لك. أعلم أنه موجود في Glassfish. (جوجل البديل على الورم الزجاجي لمعرفة كيف يعمل.)

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

ولكن كما ذكرت أنه لا يوجد خيار آخر ولكن لتدفقها من خلال Servlet أو شيء أعتقد أنه يمكنني الاحتفاظ بها خارج دليل Tomcat.

أردت تجنب كتابة هذا servlet. مجرد مشروع صغير جدا للتعامل مع جميع الفوضى (مثل نوع المحتوى المناسب، 404، إلخ) أثناء كتابة Servlet Servlet.

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Image streaming Servlet.
 */
public class ImageDisplayServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public ImageDisplayServlet() {
        super();
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String relativePath = trimToEmpty(request.getPathInfo());

        // Make sure no one try to screw with us. 
        // This is important as user can literally access any file if we are not careful
        if(isXSSAttack(relativePath) == false) {
            String pathToFile = this.getServletContext().getRealPath(request.getPathInfo());
            File file = new File(pathToFile);

            System.out.println("Looking for file " + file.getAbsolutePath());

            // show a 404 page
            if(!file.exists() || !file.isFile()) {
                httpError(404, response);
            } else {
                try {
                    streamImageFile(file, response);
                } catch(Exception e) {
                    // Tell the user there was some internal server error.\
                    // 500 - Internal server error.
                    httpError(500, response);
                    e.printStackTrace();
                }
            }
        } else {
            // what to do if i think it is a XSS attack ?!?
        }
    }

    private void streamImageFile(File file, HttpServletResponse response) {
        // find the right MIME type and set it as content type
        response.setContentType(getContentType(file));
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            response.setContentLength((int) file.length());

            // Use Buffered Stream for reading/writing.
            bis = new BufferedInputStream(new FileInputStream(file));
            bos = new BufferedOutputStream(response.getOutputStream());

            byte[] buff = new byte[(int) file.length()];
            int bytesRead;

            // Simple read/write loop.
            while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                bos.write(buff, 0, bytesRead);
            }
        } catch (Exception e) {

            throw new RuntimeException(e);
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    // To late to do anything about it now, we may have already sent some data to user.
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    // To late to do anything about it now, we may have already sent some data to user.
                }
            }
        } 
    }

    private String getContentType(File file) {
        if(file.getName().length() > 0) {
            String[] parts = file.getName().split("\\.");
            if(parts.length > 0) {
                // only last part interests me
                String extention = parts[parts.length - 1];
                if(extention.equalsIgnoreCase("jpg")) {
                    return "image/jpg";
                } else if(extention.equalsIgnoreCase("gif")) {
                    return "image/gif"; 
                } else if(extention.equalsIgnoreCase("png")) {
                    return "image/png";
                }
            }
        }
        throw new RuntimeException("Can not find content type for the file " +  file.getAbsolutePath());
    }

    private String trimToEmpty(String pathInfo) {
        if(pathInfo == null) {
            return "";
        } else {
            return pathInfo.trim();
        }
    }

    private void httpError(int statusCode, HttpServletResponse response) {
        try {
            response.setStatus(statusCode);
            response.setContentType("text/html");
            PrintWriter writer = response.getWriter();
            writer.append("<html><body><h1>Error Code: " + statusCode + "</h1><body></html>");
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private boolean isXSSAttack(String path) {
        boolean xss = false;
        // Split on the bases of know file separator
        String[] parts = path.split("/|\\\\");

        // Now verify that no part contains anything harmful
        for(String part : parts) {
            // No double dots .. 
            // No colons :
            // No semicolons ;
            if(part.trim().contains("..") || part.trim().contains(":") || part.trim().contains(";")) {
                // Fire in the hole!
                xss = true;
                break;
            }
        }
        return xss;
    }

    /**
     * @see HttpServlet#doPost(Ht/promotions/some.jpgtpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

حسنا، إليك Servlet التي كتبتها بسرعة يمكن أن تدفق الصور:

فيما يلي قائمة القيود ومعرفة القضايا:

  • قد يكون لديك ضعف XSS مع الرعاية
  • عدم الإنتاج استخدام جاهز كمرجع
  • الصور تحتاج إلى في دليل تطبيق الويب. يمكن تغييرها بسهولة ولكنني كسول جدا (لا يستحق كل هذا الأمر صغير جدا)
  • فقط دفق JPG أو GIF أو ملفات PNG.

الاستعمال:

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

http://www.example.com/images/promotions/promo.jpg.

يعني أنه يجب أن يكون هناك دليل في "الترقيات" مع صورة "promo.jpg" في تطبيق الصور هذه.

ملاحظة: لا تسأل لماذا أقوم بحل حاوية Servlet هذا فقط يمتص وقتا كبيرا.

  <servlet>
    <description></description>
    <display-name>ImageDisplayServlet</display-name>
    <servlet-name>ImageDisplayServlet</servlet-name>
    <servlet-class>com.example.images.ImageDisplayServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ImageDisplayServlet</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>

يا يا تكوين Servlet مثل أعلاه للحصول على أفضل النتائج: P

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