একটি সার্লেট অ্যাপ্লিকেশনটিতে আপলোড করা ফাইলগুলি সংরক্ষণ করার প্রস্তাবিত উপায়


121

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

  • ফাইল সংরক্ষণের জন্য সেরা স্থানটি কী? আমি কি এটিকে এখানে বাঁচাতে পারি /WEB-INF/uploads( এখানে বিরুদ্ধে পরামর্শ দেওয়া ) বা কোথাও কোথাও $CATALINA_BASE( এখানে দেখুন ) বা ...? জাভাএই 6 টি টিউটোরিয়ালটি ব্যবহারকারীর কাছ থেকে পাথ পাবে (: wtf :)। এনবি: ফাইলটি কোনও উপায়ে ডাউনলোড করা উচিত নয়।

  • আমি এখানে বিশদ হিসাবে একটি কনফিগার পরামিতি সেট আপ করা উচিত ? আমি কিছু কোডের প্রশংসা করব (আমি বরং এটি একটি আপেক্ষিক পথ দেব - সুতরাং এটি কমপক্ষে টমক্যাট বহনযোগ্য) - Part.write()আশাব্যঞ্জক দেখাচ্ছে - তবে দৃশ্যত একটি নিখুঁত পথের প্রয়োজন

  • আমি এই পদ্ধতির বনাম একটি ডাটাবেস / জেসিআর রিপোজিটরির অসুবিধাগুলি প্রকাশ করতে আগ্রহী

দুর্ভাগ্যক্রমে @ বালাসক দ্বারা ফাইল সার্ভারলেট ফাইলগুলি ডাউনলোড করার দিকে মনোনিবেশ করে, অন্যদিকে ফাইলগুলি আপলোড করার ক্ষেত্রে তার উত্তরটি ফাইলটি কোথায় সংরক্ষণ করবেন সে অংশটি এড়িয়ে যায়।

একটি সমাধান খুব সহজেই পরিবর্তনীয় একটি ডিবি বা JCR বাস্তবায়ন (যেমন ব্যবহার করতে jackrabbit ) বাঞ্ছনীয় হবে।


এটি করার আমার চূড়ান্ত
পদ্ধতির জন্য

উত্তর:


165

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

  1. আইডিইর প্রকল্প ফোল্ডারে পরিবর্তনগুলি তত্ক্ষণাত্ সার্ভারের কাজের ফোল্ডারে প্রতিফলিত হয় না। আইডিইতে এক ধরণের পটভূমি কাজ রয়েছে যা যত্ন করে যে সার্ভারের কাজের ফোল্ডারটি সর্বশেষ আপডেটের সাথে সিঙ্ক হয়ে যায় (এটি আইডিই পদটিতে "প্রকাশনা" নামে পরিচিত)। আপনি যে সমস্যার মুখোমুখি হচ্ছেন এটিই এর মূল কারণ।

  2. রিয়েল ওয়ার্ল্ড কোডে এমন পরিস্থিতি রয়েছে যেখানে ওয়েব অ্যাপের মোতায়েন ফোল্ডারে আপলোড করা ফাইলগুলি সংরক্ষণ করা মোটেই কার্যকর হবে না। কিছু সার্ভার (ডিফল্ট বা কনফিগারেশনের মাধ্যমে) স্থানীয় ডিস্ক ফাইল সিস্টেমে মোতায়েন করা ওয়ার ফাইলটি প্রসারিত করে না, পরিবর্তে পুরোপুরি মেমরিতে থাকে। মূলত মোতায়েন হওয়া ওয়ার ফাইলটি সম্পাদনা এবং পুনরায় প্রচার না করে আপনি মেমোরিতে নতুন ফাইল তৈরি করতে পারবেন না।

  3. এমনকি সার্ভার যখন স্থানীয় ডিস্ক ফাইল সিস্টেমে মোতায়েন করা ওয়ার ফাইলটি প্রসারিত করে, তখন নতুনভাবে তৈরি করা সমস্ত ফাইল একটি পুনর্নির্বাচিত বা এমনকি একটি সাধারণ পুনঃসূচনাতে হারিয়ে যাবে, কেবলমাত্র এই নতুন ফাইলগুলি মূল ওয়ার ফাইলের অংশ নয়।

এটা সত্যিই আমাকে বা অন্য কেউ ঠিক যেখানে স্থানীয় ডিস্কে ফাইল সিস্টেমে এটা দীর্ঘ হিসাবে আপনি হিসাবে, সংরক্ষণ করা হবে কাছে কোন ব্যাপার না না না কি ব্যবহার getRealPath()পদ্ধতি । এই পদ্ধতিটি ব্যবহার করা যে কোনও ক্ষেত্রে উদ্বেগজনক।

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

সুতরাং, চূড়ান্ত স্টোরেজ অবস্থানের পথটি নিম্নলিখিত যে কোনও একটি দিয়ে সুনির্দিষ্ট করা যেতে পারে:

  • হার্ডকোডেড:

      File uploads = new File("/path/to/uploads");
  • এর মাধ্যমে পরিবেশ পরিবর্তনশীল SET UPLOAD_LOCATION=/path/to/uploads:

      File uploads = new File(System.getenv("UPLOAD_LOCATION"));
  • এর মাধ্যমে সার্ভার শুরুর সময় ভিএম যুক্তি -Dupload.location="/path/to/uploads":

      File uploads = new File(System.getProperty("upload.location"));
  • *.propertiesফাইল এন্ট্রি হিসাবে upload.location=/path/to/uploads:

      File uploads = new File(properties.getProperty("upload.location"));
  • web.xml <context-param>নাম upload.locationএবং মান সহ /path/to/uploads:

      File uploads = new File(getServletContext().getInitParameter("upload.location"));
  • যদি কোনও হয় তবে সার্ভার-সরবরাহিত অবস্থানটি ব্যবহার করুন, যেমন জেবস এএস / ওয়াইল্ডফ্লাইতে :

      File uploads = new File(System.getProperty("jboss.server.data.dir"), "uploads");

যে কোনও উপায়ে, আপনি সহজেই ফাইলটিকে নিম্নরূপ হিসাবে উল্লেখ এবং সংরক্ষণ করতে পারেন:

File file = new File(uploads, "somefilename.ext");

try (InputStream input = part.getInputStream()) {
    Files.copy(input, file.toPath());
}

বা, যখন আপনি কাকতালীয়ভাবে একই নামের সাথে বিদ্যমান ফাইলগুলিকে ওভাররাইট করা থেকে ব্যবহারকারীদের একটি অনন্য ফাইলের নাম স্বয়ংক্রিয়ভাবে তৈরি করতে চান:

File file = File.createTempFile("somefilename-", ".ext", uploads);

try (InputStream input = part.getInputStream()) {
    Files.copy(input, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
}

partজেএসপি / সার্লেটতে কীভাবে প্রাপ্ত হবে তার জবাব দেওয়া হয় কীভাবে জেএসপি / সার্লেট ব্যবহার করে সার্ভারে ফাইল আপলোড করা যায়? এবং partজেএসএফ-এ কীভাবে প্রাপ্ত হবে তার জবাব দেওয়া হয় জেএসএফ ২.২ <এইচ: ইনপুট ফাইল> ব্যবহার করে ফাইল কীভাবে আপলোড করবেন? সেভ করা ফাইলটি কোথায়?

দ্রষ্টব্য: এটি সংজ্ঞায়িত অস্থায়ী স্টোরেজ অবস্থানের সাথে সম্পর্কিত পথটির ব্যাখ্যা হিসাবে ব্যবহার করবেন নাPart#write()@MultipartConfig(location)

আরো দেখুন:


@MultipartConfig(location)নির্দিষ্ট করে অস্থায়ী storge অবস্থান যখন ফাইল সাইজ মেমরির সঞ্চয়ের জন্য থ্রেশহোল্ড অতিক্রম করে যা সার্ভার ব্যবহার করা উচিত, না স্থায়ী সংগ্রহস্থলের অবস্থান যেখানে আপনি শেষ পর্যন্ত এটা চাই সঞ্চিত হবে। java.io.tmpdirসিস্টেম সম্পত্তি দ্বারা চিহ্নিত হিসাবে এই মানটি ডিফল্ট হয় । : এছাড়াও একটি ব্যর্থ JSF প্রয়াস এই সংশ্লিষ্ট উত্তর দেখার stackoverflow.com/questions/18478154/...
BalusC


হ্যাঁ, আপনি যদি ইতিমধ্যে সার্লেট ৩.০ এ থাকেন তবে আপনি এটি ব্যবহার করতে পারেন Part#write()। আমি উত্তর দিয়ে এটি আপডেট।
বালুসসি

পোস্টটি আপডেট রাখার জন্য আপনাকে অনেক ধন্যবাদ - টমক্যাটের মতো কোনও সম্পত্তি আছে "jboss.server.data.dir"কি?
মিস্টার_আর_আমস_ডি

1
না, এটা নেই।
বালুসসি

7

আমি স্বীকৃত উত্তরের ভিত্তিতে এটি করার আমার চূড়ান্ত উপায় পোস্ট করি:

@SuppressWarnings("serial")
@WebServlet("/")
@MultipartConfig
public final class DataCollectionServlet extends Controller {

    private static final String UPLOAD_LOCATION_PROPERTY_KEY="upload.location";
    private String uploadsDirName;

    @Override
    public void init() throws ServletException {
        super.init();
        uploadsDirName = property(UPLOAD_LOCATION_PROPERTY_KEY);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // ...
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        Collection<Part> parts = req.getParts();
        for (Part part : parts) {
            File save = new File(uploadsDirName, getFilename(part) + "_"
                + System.currentTimeMillis());
            final String absolutePath = save.getAbsolutePath();
            log.debug(absolutePath);
            part.write(absolutePath);
            sc.getRequestDispatcher(DATA_COLLECTION_JSP).forward(req, resp);
        }
    }

    // helpers
    private static String getFilename(Part part) {
        // courtesy of BalusC : http://stackoverflow.com/a/2424824/281545
        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;
    }
}

কোথায় :

@SuppressWarnings("serial")
class Controller extends HttpServlet {

    static final String DATA_COLLECTION_JSP="/WEB-INF/jsp/data_collection.jsp";
    static ServletContext sc;
    Logger log;
    // private
    // "/WEB-INF/app.properties" also works...
    private static final String PROPERTIES_PATH = "WEB-INF/app.properties";
    private Properties properties;

    @Override
    public void init() throws ServletException {
        super.init();
        // synchronize !
        if (sc == null) sc = getServletContext();
        log = LoggerFactory.getLogger(this.getClass());
        try {
            loadProperties();
        } catch (IOException e) {
            throw new RuntimeException("Can't load properties file", e);
        }
    }

    private void loadProperties() throws IOException {
        try(InputStream is= sc.getResourceAsStream(PROPERTIES_PATH)) {
                if (is == null)
                    throw new RuntimeException("Can't locate properties file");
                properties = new Properties();
                properties.load(is);
        }
    }

    String property(final String key) {
        return properties.getProperty(key);
    }
}

এবং / WEB-INF/app.properties:

upload.location=C:/_/

এইচটিএইচ এবং যদি আপনি কোনও বাগ পান তবে আমাকে জানান


1
আমি যদি কোনও এসও স্বাধীন সমাধান চাই, যা উভয় ক্ষেত্রে (উইন / ইউএক্স) কাজ করে? আমার কি আলাদা আপলোড.লোকশন পথ নির্ধারণ করতে হবে বা অন্য কোনও ইঙ্গিত রয়েছে?
পিকিমোটা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.