Bir URL'den InputStream


117

Bir URL'den nasıl InputStream alabilirim?

örneğin, wwww.somewebsite.com/a.txturl'deki dosyayı almak ve bir sunucu uygulaması aracılığıyla Java'da InputStream olarak okumak istiyorum .

denedim

InputStream is = new FileInputStream("wwww.somewebsite.com/a.txt");

ama aldığım şey bir hataydı:

java.io.FileNotFoundException

1
servletsEtiketin kaldırılmasını neden geri aldınız ? Burada herhangi bir javax.servlet.*API yoktur . Basit bir Java sınıfında bir main()yöntemle bunu yaparken de tam olarak aynı sorunu yaşarsınız .
BalusC

1
Belki de bir URL'nin ne olduğunu öğrenmelisiniz
b1nary.atr0phy

Yanıtlar:


228

java.net.URL#openStream()Uygun bir URL ile kullanın (protokol dahil!). Örneğin

InputStream input = new URL("http://www.somewebsite.com/a.txt").openStream();
// ...

Ayrıca bakınız:


2
Bunun, InputStream'in her okumasında bir ağ isteği yapıp yapmadığını veya tüm dosyayı bir kerede okuyup okumadığını, böylece okumalarda ağ istekleri yapmak zorunda kalmayacağını biliyor musunuz?
gsingh2011

Android'de UI iş parçacığında bu yöntemi çağırmak bir istisna oluşturacaktır. Bir arka plan dizisinde yapın. Bolts-Android'i
Behrouz.M

19

Deneyin:

final InputStream is = new URL("http://wwww.somewebsite.com/a.txt").openStream();

10

(a) wwww.somewebsite.com/a.txtbir 'dosya URL'si' değildir. Hiç bir URL değil. Önüne koyarsanız http://, bir HTTP URL'si olur, ki bu açıkça burada niyet ettiğiniz şeydir.

(b) FileInputStreamdosyalar içindir, URL'ler için değil.

(c) Herhangi bir URL'den bir giriş akışı almanın yolu yoluyladır URL.openStream(),veya URL.getConnection().getInputStream(),eşdeğerdir, ancak URLConnectionönce onu almak ve onunla oynamak için başka nedenleriniz olabilir .


4

Orijinal kodunuz, dosya sistemi tarafından barındırılan dosyalara erişmek için FileInputStream kullanır.

Kullandığınız kurucu, geçerli çalışma dizininin www.somewebsite.com alt klasöründe (user.dir sistem özelliği değeri) a.txt adlı bir dosyayı bulmaya çalışacaktır. Sağladığınız ad, File sınıfı kullanılarak bir dosyaya çözümlenir.

URL nesneleri, bunu çözmenin genel yoludur. Yerel dosyalara ve ayrıca ağda barındırılan kaynaklara erişmek için URL'leri kullanabilirsiniz. URL sınıfı, http: // veya https: //'nin yanı sıra file: // protokolünü de destekler, bu nedenle gitmekte fayda var.


2

Saf Java:

 urlToInputStream(url,httpHeaders);

Biraz başarı ile bu yöntemi kullanıyorum. Bu yönlendirmeleri kolları ve bir değişken bir sayı da HTTP üst olarak Map<String,String>. Ayrıca HTTP'den HTTPS'ye yönlendirmelere izin verir .

private InputStream urlToInputStream(URL url, Map<String, String> args) {
    HttpURLConnection con = null;
    InputStream inputStream = null;
    try {
        con = (HttpURLConnection) url.openConnection();
        con.setConnectTimeout(15000);
        con.setReadTimeout(15000);
        if (args != null) {
            for (Entry<String, String> e : args.entrySet()) {
                con.setRequestProperty(e.getKey(), e.getValue());
            }
        }
        con.connect();
        int responseCode = con.getResponseCode();
        /* By default the connection will follow redirects. The following
         * block is only entered if the implementation of HttpURLConnection
         * does not perform the redirect. The exact behavior depends to 
         * the actual implementation (e.g. sun.net).
         * !!! Attention: This block allows the connection to 
         * switch protocols (e.g. HTTP to HTTPS), which is <b>not</b> 
         * default behavior. See: /programming/1884230 
         * for more info!!!
         */
        if (responseCode < 400 && responseCode > 299) {
            String redirectUrl = con.getHeaderField("Location");
            try {
                URL newUrl = new URL(redirectUrl);
                return urlToInputStream(newUrl, args);
            } catch (MalformedURLException e) {
                URL newUrl = new URL(url.getProtocol() + "://" + url.getHost() + redirectUrl);
                return urlToInputStream(newUrl, args);
            }
        }
        /*!!!!!*/

        inputStream = con.getInputStream();
        return inputStream;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

Tam örnek çağrı

private InputStream getInputStreamFromUrl(URL url, String user, String passwd) throws IOException {
        String encoded = Base64.getEncoder().encodeToString((user + ":" + passwd).getBytes(StandardCharsets.UTF_8));
        Map<String,String> httpHeaders=new Map<>();
        httpHeaders.put("Accept", "application/json");
        httpHeaders.put("User-Agent", "myApplication");
        httpHeaders.put("Authorization", "Basic " + encoded);
        return urlToInputStream(url,httpHeaders);
    }

HttpURLConnectionSiz yapmadığınız sürece zaten yönlendirmeleri izleyecektir.
Marquis of Lorne

1
OP'nin başlıklardan bahsetmediğini biliyorum ama özlü (Java olduğu düşünüldüğünde) örneğini takdir ediyorum.
chbrown

@EJP Satır içi yorum olarak bazı açıklamalar ekledim. Sanırım, HTTP 301 bir HTTP adresini bir HTTPS adresine yönlendirdiğinde esas olarak yönlendirme bloğunu tanıttım. Tabii ki, bu orijinal sorunun ötesine geçer, ancak varsayılan uygulama tarafından ele alınmayan yaygın bir kullanım durumudur. Bakınız: stackoverflow.com/questions/1884230/…
jschnasse

Kodunuz HttpURLConnection, daha önce de belirttiğim gibi, varsayılan olarak yönlendirmeleri zaten takip ettiği gibi, yönlendirme bloğu olmadan eşit derecede iyi çalışır .
Marquis of Lorne

@ user207421 Bu kısmen doğrudur. Yönlendirme bloğu, varsayılan olarak desteklenmeyen http-> https gibi protokol anahtarları içindir. Bunu kod içi yorumda ifade etmeye çalıştım. Bkz stackoverflow.com/questions/1884230/... .
jschnasse

-1

İşte verilen web sayfasının içeriğini okuyan tam bir örnek. Web sayfası bir HTML formundan okunur. Standart InputStreamsınıfları kullanıyoruz, ancak JSoup kütüphanesi ile daha kolay yapılabilir.

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>

</dependency>

<dependency>
    <groupId>commons-validator</groupId>
    <artifactId>commons-validator</artifactId>
    <version>1.6</version>
</dependency>  

Bunlar Maven bağımlılıklarıdır. URL dizelerini doğrulamak için Apache Commons kitaplığını kullanıyoruz.

package com.zetcode.web;

import com.zetcode.service.WebPageReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "ReadWebPage", urlPatterns = {"/ReadWebPage"})
public class ReadWebpage extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setContentType("text/plain;charset=UTF-8");

        String page = request.getParameter("webpage");

        String content = new WebPageReader().setWebPageName(page).getWebPageContent();

        ServletOutputStream os = response.getOutputStream();
        os.write(content.getBytes(StandardCharsets.UTF_8));
    }
}

ReadWebPageServlet verilen web sayfasının içeriğini okur ve düz metin biçiminde müşteriye geri gönderir. Sayfayı okuma görevi devredilmiştir WebPageReader.

package com.zetcode.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.apache.commons.validator.routines.UrlValidator;

public class WebPageReader {

    private String webpage;
    private String content;

    public WebPageReader setWebPageName(String name) {

        webpage = name;
        return this;
    }

    public String getWebPageContent() {

        try {

            boolean valid = validateUrl(webpage);

            if (!valid) {

                content = "Invalid URL; use http(s)://www.example.com format";
                return content;
            }

            URL url = new URL(webpage);

            try (InputStream is = url.openStream();
                    BufferedReader br = new BufferedReader(
                            new InputStreamReader(is, StandardCharsets.UTF_8))) {

                content = br.lines().collect(
                      Collectors.joining(System.lineSeparator()));
            }

        } catch (IOException ex) {

            content = String.format("Cannot read webpage %s", ex);
            Logger.getLogger(WebPageReader.class.getName()).log(Level.SEVERE, null, ex);
        }

        return content;
    }

    private boolean validateUrl(String webpage) {

        UrlValidator urlValidator = new UrlValidator();

        return urlValidator.isValid(webpage);
    }
}

WebPageReaderURL'yi doğrular ve web sayfasının içeriğini okur. Sayfanın HTML kodunu içeren bir dize döndürür.

<!DOCTYPE html>
<html>
    <head>
        <title>Home page</title>
        <meta charset="UTF-8">
    </head>
    <body>
        <form action="ReadWebPage">

            <label for="page">Enter a web page name:</label>
            <input  type="text" id="page" name="webpage">

            <button type="submit">Submit</button>

        </form>
    </body>
</html>

Son olarak, bu HTML formunu içeren ana sayfadır. Bu benim alınır öğretici bu konu hakkında.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.