Java 웹 애플리케이션에서 애플리케이션 서버 외부에서 정적 데이터를 제공하는 가장 간단한 방법
Tomcat에서 실행되는 Java 웹 응용 프로그램이 있습니다. 웹 UI와 응용 프로그램에서 생성 된 PDF 파일 모두에 표시되는 정적 이미지를로드하고 싶습니다. 또한 웹 UI를 통해 업로드하면 새로운 이미지가 추가되고 저장됩니다.
정적 데이터를 웹 컨테이너 내에 저장하지만 웹 컨테이너 외부에서 저장 및로드하여 두통을 유발 하여이 작업을 수행하는 것은 문제가되지 않습니다.
이 시점에서 정적 데이터를 제공하기 위해 Apache와 같은 별도의 웹 서버를 사용하지 않는 것이 좋습니다. 또한 이미지를 데이터베이스에 바이너리로 저장하는 것을 좋아하지 않습니다.
이미지 디렉토리를 웹 컨테이너 외부의 디렉토리를 가리키는 기호 링크로 만드는 것과 같은 제안을 보았지만이 방법은 Windows 및 * nix 환경에서 모두 작동합니까?
일부는 이미지 제공을 처리하기 위해 필터 또는 서블릿을 작성하도록 제안하지만 이러한 제안은이를 수행하는 방법에 대한 자세한 정보에 대한 포인터없이 매우 모호하고 고급입니다.
이미지 디렉토리를 웹 컨테이너 외부의 디렉토리를 가리키는 기호 링크로 만드는 것과 같은 제안을 보았지만이 방법은 Windows 및 * nix 환경에서 모두 작동합니까?
* nix 파일 시스템 경로 규칙을 준수하는 경우 (즉 /path/to/files
, 에서와 같이 슬래시를 독점적으로 사용하는 경우 ) 추악한 File.separator
문자열 연결 을 피할 필요없이 Windows에서도 작동합니다 . 그러나이 명령이 호출 된 곳과 동일한 작업 디스크에서만 스캔됩니다. Tomcat이 설치 예를 들어, 경우에 따라서 C:
다음 /path/to/files
사실을 가리 것이다 C:\path\to\files
.
파일이 모두 webapp 외부에 있고 Tomcat DefaultServlet
이 처리하도록하려면 Tomcat에서 기본적으로해야 할 일은 태그 /conf/server.xml
내부에 다음 Context 요소를 추가하는 것입니다 <Host>
.
<Context docBase="/path/to/files" path="/files" />
이 방법으로을 통해 액세스 할 수 있습니다 http://example.com/files/...
. GlassFish / Payara 구성 예는 여기에서 , WildFly 구성 예는 여기 에서 찾을 수 있습니다 .
파일 읽기 / 쓰기를 직접 제어하려면 Servlet
기본적으로 InputStream
파일을 가져 와서 의 파일에 FileInputStream
쓰는 파일을 작성해야 OutputStream
합니다 HttpServletResponse
.
응답 Content-Type
에서 클라이언트가 제공된 파일과 연관시킬 응용 프로그램을 알 수 있도록 헤더를 설정해야 합니다. 그리고 Content-Length
클라이언트가 다운로드 진행률을 계산할 수 있도록 헤더를 설정해야합니다 . 그렇지 않으면 알 수 없습니다. 다른 이름 으로 저장 대화 상자 를 원하면 Content-Disposition
헤더를로 설정해야합니다 . 그렇지 않으면 클라이언트가 인라인 표시를 시도합니다. 마지막으로 파일 내용을 응답 출력 스트림에 씁니다.attachment
이러한 서블릿의 기본 예는 다음과 같습니다.
@WebServlet("/files/*")
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String filename = URLDecoder.decode(request.getPathInfo().substring(1), "UTF-8");
File file = new File("/path/to/files", filename);
response.setHeader("Content-Type", getServletContext().getMimeType(filename));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
Files.copy(file.toPath(), response.getOutputStream());
}
}
url-pattern
예를 들어의에 매핑 된 경우 /files/*
이를 호출 할 수 있습니다 http://example.com/files/image.png
. 이 방법 DefaultServlet
으로 기본 이미지 제공 등 의 요청보다 요청을 더 많이 제어 할 수 있습니다 if (!file.exists()) file = new File("/path/to/files", "404.gif")
. 또한 SEO에 더 친숙하고 IE가 다른 이름으로 저장 중에 올바른 파일 이름을 선택하지 않기 때문에 request.getPathInfo()
위의를 사용하는 것이 좋습니다 .request.getParameter()
데이터베이스에서 파일을 제공하기 위해 동일한 논리를 재사용 할 수 있습니다. 간단하게 교체 new FileInputStream()
에 의해 ResultSet#getInputStream()
.
도움이 되었기를 바랍니다.
또한보십시오:
- 서블릿 애플리케이션에 업로드 된 파일을 저장하는 권장 방법
- 정적 자원 서블릿에 대한 추상 템플리트 (HTTP 캐시 지원)
- JSP 페이지에서 데이터베이스에서 이미지를 검색하고 표시하는 방법은 무엇입니까?
- 서블릿을 사용하여 MP3, MP4, AVI 등과 같은 오디오 / 비디오 파일을 스트리밍하는 방법
이미지를 고정 경로 (예 : / var / images 또는 c : \ images)에 놓고 응용 프로그램 설정 (Settings.class에서 내 예제에 표시)에 설정을 추가 한 다음로드하면됩니다. HttpServlet
당신의 것에서 와 같이 :
String filename = Settings.getValue("images.path") + request.getParameter("imageName")
FileInputStream fis = new FileInputStream(filename);
int b = 0;
while ((b = fis.read()) != -1) {
response.getOutputStream().write(b);
}
또는 이미지를 조작하려는 경우 :
String filename = Settings.getValue("images.path") + request.getParameter("imageName")
File imageFile = new File(filename);
BufferedImage image = ImageIO.read(imageFile);
ImageIO.write(image, "image/png", response.getOutputStream());
html 코드는 <img src="imageServlet?imageName=myimage.png" />
물론 파일 확장자에 따라 "image / jpeg"와 같은 다른 컨텐츠 유형을 제공하는 것을 고려해야합니다. 또한 일부 캐싱을 제공해야합니다.
또한 너비 및 높이 매개 변수를 인수로 제공하고 image.getScaledInstance(w, h, Image.SCALE_SMOOTH
성능을 고려 하여 )를 사용하여 이미지의 품질 재조정에이 서블릿을 사용할 수 있습니다 .
요구 사항 : WEBROOT 디렉토리 외부 또는 로컬 디스크에서 정적 리소스 (이미지 / 비디오 등)에 액세스
1 단계 :
Tomcat 서버의 webapps 아래에 폴더를 만듭니다., 폴더 이름이 myproj라고 가정 해 봅시다.
2 단계 :
myproj에서 WEB-INF 폴더를 작성하십시오.이 아래에 간단한 web.xml을 작성하십시오.
web.xml의 코드
<web-app>
</web-app>
위의 두 단계에 대한 디렉토리 구조
c:\programfile\apachesoftwarefoundation\tomcat\...\webapps
|
|---myproj
| |
| |---WEB-INF
| |
|---web.xml
3 단계 :
이제 다음 위치에 이름이 myproj.xml 인 xml 파일을 작성하십시오.
c:\programfile\apachesoftwarefoundation\tomcat\conf\catalina\localhost
myproj.xml의 코드 :
<Context path="/myproj/images" docBase="e:/myproj/" crossContext="false" debug="0" reloadable="true" privileged="true" />
4 단계 :
4 A) 이제 하드 디스크의 E 드라이브에 이름이 myproj 인 폴더를 만들고 새 폴더를 만듭니다.
이름 이미지가있는 폴더 및 이미지 폴더에 일부 이미지 배치 (e:myproj\images\)
myfoto.jpg가 아래에 있다고 가정 해 봅시다. e:\myproj\images\myfoto.jpg
B) 이제 이름이 WEB-INF 인 폴더를 e:\myproj\WEB-INF
만들고 WEB-INF 폴더에 web.xml을 만듭니다.
Code in web.xml
<web-app>
</web-app>
Step 5:
Now create a .html document with name index.html and place under e:\myproj
CODE under index.html Welcome to Myproj
The Directory Structure for the above Step 4 and Step 5 is as follows
E:\myproj
|--index.html
|
|--images
| |----myfoto.jpg
|
|--WEB-INF
| |--web.xml
Step 6:
Now start the apache tomcat server
Step 7:
open the browser and type the url as follows
http://localhost:8080/myproj
then u display the content which is provided in index.html
Step 8:
To Access the Images under your local hard disk (outside of webroot)
http://localhost:8080/myproj/images/myfoto.jpg
This is story from my workplace:
- We try to upload multiply images and document files use Struts 1 and Tomcat 7.x.
- We try to write uploaded files to file system, filename and full path to database records.
- We try to separate file folders outside web app directory. (*)
The below solution is pretty simple, effective for requirement (*):
In file META-INF/context.xml
file with the following content: (Example, my application run at http://localhost:8080/ABC
, my application / project named ABC
). (this is also full content of file context.xml
)
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/ABC" aliases="/images=D:\images,/docs=D:\docs"/>
(works with Tomcat version 7 or later)
Result: We have been created 2 alias. For example, we save images at: D:\images\foo.jpg
and view from link or using image tag:
<img src="http://localhost:8080/ABC/images/foo.jsp" alt="Foo" height="142" width="142">
or
<img src="/images/foo.jsp" alt="Foo" height="142" width="142">
(I use Netbeans 7.x, Netbeans seem auto create file WEB-INF\context.xml
)
Add to server.xml :
<Context docBase="c:/dirtoshare" path="/dir" />
Enable dir file listing parameter in web.xml :
<init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>
If you decide to dispatch to FileServlet
then you will also need allowLinking="true"
in context.xml
in order to allow FileServlet
to traverse the symlinks.
See http://tomcat.apache.org/tomcat-6.0-doc/config/context.html
if anyone not able to resolve his problem with accepted answer, then note these below considerations:
- no need to mention
localhost:<port>
with<img> src
attribute. - make sure you are running this project outside eclipse, because eclipse creates
context docBase
entry on its own inside its localserver.xml
file.
Read the InputStream of a file and write it to ServletOutputStream
for sending binary data to the client.
- Local file You can read a file directly using FileInputStream('path/image.png').
- Mongo DataBase file's you can get InputStream using GridFS.
@WebServlet("/files/URLStream")
public class URLStream extends HttpServlet {
private static final long serialVersionUID = 1L;
public URLStream() {
super();
}
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
File source = new File("D:\\SVN_Commit.PNG");
long start = System.nanoTime();
InputStream image = new FileInputStream(source);
/*String fileID = request.getParameter("id");
System.out.println("Requested File ID : "+fileID);
// Mongo DB GridFS - https://stackoverflow.com/a/33544285/5081877
image = outputImageFile.getInputStream();*/
if( image != null ) {
BufferedInputStream bin = null;
BufferedOutputStream bout = null;
ServletOutputStream sos = response.getOutputStream();
try {
bin = new BufferedInputStream( image );
bout = new BufferedOutputStream( sos );
int ch =0; ;
while((ch=bin.read())!=-1) {
bout.write(ch);
}
} finally {
bin.close();
image.close();
bout.close();
sos.close();
}
} else {
PrintWriter writer = response.getWriter();
writer.append("Something went wrong with your request.");
System.out.println("Image not available.");
}
System.out.println("Time taken by Stream Copy = "+(System.nanoTime()-start));
}
}
Result the URL directly to the src
attibute.
<img src='http://172.0.0.1:8080/ServletApp/files/URLStream?id=5a575be200c117cc2500003b' alt="mongodb File"/>
<img src='http://172.0.0.1:8080/ServletApp/files/URLStream' alt="local file"/>
<video controls="controls" src="http://172.0.0.1:8080/ServletApp/files/URLStream"></video>
If you want to work with JAX-RS (e.g. RESTEasy) try this:
@Path("/pic")
public Response get(@QueryParam("url") final String url) {
String picUrl = URLDecoder.decode(url, "UTF-8");
return Response.ok(sendPicAsStream(picUrl))
.header(HttpHeaders.CONTENT_TYPE, "image/jpg")
.build();
}
private StreamingOutput sendPicAsStream(String picUrl) {
return output -> {
try (InputStream is = (new URL(picUrl)).openStream()) {
ByteStreams.copy(is, output);
}
};
}
using javax.ws.rs.core.Response
and com.google.common.io.ByteStreams
I did it even simpler. Problem: A CSS file had url links to img folder. Gets 404.
I looked at url, http://tomcatfolder:port/img/blablah.png, which does not exist. But, that is really pointing to the ROOT app in Tomcat.
So I just copied the img folder from my webapp into that ROOT app. Works!
Not recommended for production, of course, but this is for an internal tool dev app.
'development' 카테고리의 다른 글
오버로드 된 함수에 대한 포인터를 어떻게 지정합니까? (0) | 2020.07.04 |
---|---|
Bazel과 Gradle의 차이점은 무엇입니까? (0) | 2020.07.04 |
차이점은 무엇입니까? (0) | 2020.07.04 |
position : fixed가 iPad 및 iPhone에서 작동하지 않습니다 (0) | 2020.07.04 |
Meyers의 Singleton 패턴 스레드 구현은 안전합니까? (0) | 2020.07.04 |