development

Java 웹 애플리케이션에서 애플리케이션 서버 외부에서 정적 데이터를 제공하는 가장 간단한 방법

big-blog 2020. 7. 4. 09:31
반응형

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().

도움이 되었기를 바랍니다.

또한보십시오:


이미지를 고정 경로 (예 : / 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:

  1. no need to mention localhost:<port> with <img> src attribute.
  2. make sure you are running this project outside eclipse, because eclipse creates context docBase entry on its own inside its local server.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.

참고URL : https://stackoverflow.com/questions/1812244/simplest-way-to-serve-static-data-from-outside-the-application-server-in-a-java

반응형