Ответ 1
Используйте java.net.URL#openStream()
с правильным URL (включая протокол!). Например.
InputStream input = new URL("http://www.somewebsite.com/a.txt").openStream();
// ...
Как получить InputStream из URL?
например, я хочу взять файл на url wwww.somewebsite.com/a.txt
и прочитать его как InputStream в Java через сервлет.
Я пробовал
InputStream is = new FileInputStream("wwww.somewebsite.com/a.txt");
но у меня была ошибка:
java.io.FileNotFoundException
Используйте java.net.URL#openStream()
с правильным URL (включая протокол!). Например.
InputStream input = new URL("http://www.somewebsite.com/a.txt").openStream();
// ...
Try:
final InputStream is = new URL("http://wwww.somewebsite.com/a.txt").openStream();
(a) wwww.somewebsite.com/a.txt
не является "URL-адресом файла". Это вовсе не URL. Если вы поместите http://
на передний план, это будет URL-адрес HTTP, что, безусловно, и здесь вы намереваетесь.
(b) FileInputStream
предназначен для файлов, а не для URL.
(c) Способ получения входного потока с любого URL-адреса - через URL.openStream(),
или URL.getConnection().getInputStream(),
что эквивалентно, но у вас могут быть другие причины получить URLConnection
и поиграть с ним первым.,
В исходном коде используется FileInputStream, который предназначен для доступа к размещенным файловым файлам.
Используемый вами конструктор попытается найти файл с именем a.txt в подпапке www.somewebsite.com текущего рабочего каталога (значение системного свойства user.dir). Имя, которое вы предоставляете, разрешено файлу с использованием класса File.
Объекты URL - это общий способ решить эту проблему. Вы можете использовать URL-адреса для доступа к локальным файлам, а также к сетевым ресурсам. Класс URL поддерживает файл://протокол, кроме http://или https://, поэтому вам хорошо идти.
С некоторым успехом я использую этот метод. Он обрабатывает перенаправления, и можно передать переменное количество заголовков 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: https://stackoverflow.com/questions/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);
}
Вот полный пример, который читает содержимое данной веб-страницы.
Веб-страница считывается из 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);
}
}
WebPageReader
проверяет URL-адрес и читает содержимое веб-страницы.
Он возвращает строку, содержащую 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-форму. Это взято из моего учебника об этой теме.