URL의 InputStream


117

URL에서 InputStream을 얻으려면 어떻게해야합니까?

예를 들어 URL에서 파일을 가져와 wwww.somewebsite.com/a.txt서블릿을 통해 Java의 InputStream으로 읽고 싶습니다 .

난 노력 했어

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

하지만 내가 얻은 것은 오류였습니다.

java.io.FileNotFoundException

1
servlets태그 제거를 롤백 한 이유는 무엇 입니까? 여기에는 javax.servlet.*API 가 없습니다 . main()메소드 를 사용하여 일반 바닐라 Java 클래스에서 그렇게 할 때 똑같은 문제가 발생 합니다.
BalusC 2011-08-03

1
아마도 당신은 URL이 무엇인지를 숙지해야합니다 docs.oracle.com/javase/tutorial/networking/urls/definition.html
b1nary.atr0phy

답변:


228

java.net.URL#openStream()적절한 URL (프로토콜 포함!)과 함께 사용하십시오 . 예

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

또한보십시오:


2
이것이 InputStream의 각 읽기에 대해 네트워크 요청을 만드는지 또는 전체 파일을 한 번에 읽어 읽기에 네트워크 요청을 할 필요가 없는지 알고 있습니까?
gsingh2011

Android의 UI 스레드에서이 메서드를 호출하면 예외가 발생합니다. 백그라운드 스레드에서 수행하십시오. Bolts-Android
Behrouz.M

19

시험:

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

10

(a) wwww.somewebsite.com/a.txt는 '파일 URL'이 아닙니다. 전혀 URL이 아닙니다. 당신 http://이 그것의 앞에 붙이면 그것은 분명히 당신이 여기서 의도 한 HTTP URL이 될 것입니다.

(b) FileInputStreamURL이 아닌 파일 용입니다.

(다)에서 입력 스트림을 얻을 수있는 방법 어떤 URL은 경유 URL.openStream(),URL.getConnection().getInputStream(),있는 것과 동일하지만, 당신이 얻을 수있는 다른 이유가있을 수 있습니다 URLConnection처음으로 놀이를.


4

원본 코드는 파일 시스템 호스팅 파일에 액세스하기위한 FileInputStream을 사용합니다.

사용한 생성자는 현재 작업 디렉터리의 www.somewebsite.com 하위 폴더 (시스템 속성 user.dir의 값)에서 a.txt라는 파일을 찾으려고 시도합니다. 제공 한 이름은 File 클래스를 사용하여 파일로 확인됩니다.

URL 객체는이 문제를 해결하는 일반적인 방법입니다. URL을 사용하여 로컬 파일뿐만 아니라 네트워크 호스팅 리소스에 액세스 할 수 있습니다. URL 클래스는 http : // 또는 https : // 외에 file : // 프로토콜을 지원하므로 계속 사용할 수 있습니다.


2

순수 자바 :

 urlToInputStream(url,httpHeaders);

약간의 성공으로 나는이 방법을 사용합니다. 그것은 리디렉션을 처리 하고 하나의 변수 번호를 전달할 수 있습니다 HTTP 헤더 등을 Map<String,String>. 또한 HTTP에서 HTTPS 로의 리디렉션을 허용 합니다.

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);
    }
}

전체 예제 호출

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);
    }

HttpURLConnection하지 말라고하지 않는 한 이미 리디렉션을 따르게됩니다.
Marquis of Lorne

1
나는 OP가 헤더를 언급하지 않았지만 간결한 (자바를 고려할 때) 예제에 감사드립니다.
chbrown

@EJP 인라인 주석으로 설명을 추가했습니다. HTTP 301이 HTTP 주소를 HTTPS 주소로 리디렉션하는 경우 주로 리디렉션 블록을 도입했다고 생각합니다. 물론 이것은 원래의 질문을 넘어서지 만 기본 구현으로 처리되지 않는 일반적인 사용 사례입니다. 참조 : stackoverflow.com/questions/1884230/…
jschnasse

HttpURLConnection이미 언급했듯이 기본적으로 리디렉션을 따르기 때문에 리디렉션 블록 없이도 코드가 똑같이 잘 작동합니다 .
Marquis of Lorne

@ user207421 이것은 부분적으로 정확합니다. 리디렉션 블록은 기본적으로 지원되지 않는 http-> https와 같은 프로토콜 스위치 용입니다. 나는 코드 내 주석에서 그것을 표현하려고 노력했습니다. stackoverflow.com/questions/1884230/…을 참조하십시오 .
jschnasse

-1

다음은 주어진 웹 페이지의 내용을 읽는 전체 예제입니다. 웹 페이지는 HTML 양식에서 읽습니다. 표준 InputStream클래스를 사용 하지만 JSoup 라이브러리를 사용하면 더 쉽게 할 수 있습니다.

<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>  

이들은 Maven 종속성입니다. Apache Commons 라이브러리를 사용하여 URL 문자열의 유효성을 검사합니다.

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));
    }
}

ReadWebPage서블릿은 특정 웹 페이지의 내용을 읽고 일반 텍스트 형식으로 클라이언트에게 전송한다. 페이지 읽기 작업은에 위임됩니다 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의 유효성을 검사하고 웹 페이지의 내용을 읽습니다. 페이지의 HTML 코드가 포함 된 문자열을 반환합니다.

<!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>

마지막으로 이것은 HTML 양식을 포함하는 홈 페이지입니다. 이것은 이 주제에 대한 내 튜토리얼 에서 가져온 것입니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.