Accessing local/shared drive with Spring MVC

2019-09-20 09:19发布

问题:

I'm pretty new to Spring MVC and need to display contents of local folder (could be NAS too) in browser. The folder has PDF files, which I want to list as URL's. On clicking any of them I should be able to view the file in question in PDF reader. My application server is Tomcat.

On running the app I can see the files as hyperlinks, but on clicking it gives HTTP 404. I think I'm missing out on some configuration somewhere. I've tried all possible settings and even searched for quite some time, but haven't got it to work yet.

Can someone kindly let me know where I'm going wrong or what I could be missing?

My dispatcher-servlet.xml looks like this:

<context:component-scan base-package="com.springapp.mvc"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/pages/"/>
    <property name="suffix" value=".jsp"/>
</bean>

Web.xml:

<servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

index.jsp:

<c:if test="${not empty dir}">
<ul>
    <c:forEach var="listValue" items="${dir}">
        <%--<li>${listValue}</li>--%>
        <%--<li><a href="${listValue}">${listValue}</a></li>--%>
        <li><a href="<c:url value="${listValue}"/>">${listValue}</a></li>
    </c:forEach>
</ul>
</c:if>

and the controller class:

@Controller
@RequestMapping("/")
public class DirListController extends AbstractController {
    private File[] getPdfFileListing() {
        File dir = new File("//Users//username//Documents"); // current directory

        return dir.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.toLowerCase().endsWith(".pdf");
            }
        });
    }

    @Override
    @RequestMapping(method = RequestMethod.GET)
    protected ModelAndView handleRequestInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        //return back to index.jsp
        File[] files = getPdfFileListing();
        ModelAndView model = new ModelAndView("index");
        model.addObject("dir", files);

        return model;
    }
}

回答1:

Accessing the whole directory at once probably isn't going to work. But what you can do, is return a single file per link as a byte array, if you use ResponseEntity as a return type. Then you can open it up in a PDF viewer.

Tested this with Spring 3.2.5, Tomcat 7 and added Apache Commons IO 1.3.2 as a dependency (for the FileUtils class).

private static final String DIRECTORY = "/Users/username/Documents/";

@RequestMapping(method = RequestMethod.GET, params = "fileName")
@ResponseBody
protected ResponseEntity<byte[]> handleFileRequest(HttpServletRequest request, HttpServletResponse response,
                                                   @RequestParam String fileName) throws Exception {
    // Change below to proper logger, if you have one configured.
    System.out.println("Trying to find file: " + fileName +
                       " from directory: " + DIRECTORY + ".");

    File pdfFile = new File(DIRECTORY + fileName);
    byte[] bytes = FileUtils.readFileToByteArray(pdfFile);

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.parseMediaType("application/pdf"));
    headers.setContentLength(bytes.length);
    headers.setContentDispositionFormData("filename", fileName);

    return new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);
}

Thus you'd have to add a fileName request parameter to the link in your URL, where you define which file to call. For instance:

<a href="http://localhost:8080/myApp?fileName=test.pdf">Open test.pdf</a>