Read a resource from URL and return directly those bytes as response of REST request, with no memory storing with Java 7 and spring MVC 3.2

半腔热情 提交于 2020-12-15 04:38:06

问题


I have a REST endpoint that has to be accessed to retrieve a resource (image, document, ...).

@RequestMapping(value = "/attachement", method = RequestMethod.GET)
@ResponseBody
public Object getTrademarkAttachement(HttpServletResponse response, HttpServletRequest request) {
    //TODO : Retrieve bytes from microservice url
    //TODO : Send bytes to frontend page
}

For retrieving this document, I want to do it via streaming . I don't want to store in memory the info . I want to , as I get the info, send the bytes as a response . My version of spring MVC is Spring MVC 3.2 and my version of java is java 7 . Is it possible to achieve this ? could you give any clue to start investigating ? . I know I'm giving little details about implementation but I'm starting with this point and I would want to get some ideas from you .

EDIT 1 :

I have achieved half of the problem . Retrieving different blocks of the url . I have used the following code

 @Override
public byte[] getTrademarkAttachement() {
    String urlSample = "http://testUrl.com";
    HttpURLConnection httpConn = null;
    String line = null;
    try {
        httpConn = (HttpURLConnection) new URL(urlSample).openConnection();
        InputStream ins = httpConn.getInputStream();
        BufferedReader is = new BufferedReader(new InputStreamReader(ins));
        while ((line = is.readLine()) != null) {
            System.out.println(line);
        }
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        httpConn.disconnect();
    }
    return null;
}

Being able to have access to the inputstream , the part that is left is returning each of this lines that I'm reading , so I can stream the response . I have to look for a method in spring MVC that gives a partial response .


回答1:


Since you can get the InputStream, you should be able to return an OutputStream as a response to the request. Take a look at this (https://stackoverflow.com/a/27742486/):

@RequestMapping(value = "/attachement", method = RequestMethod.GET)
@ResponseBody
public void getAttachment(OutputStream out) {

    InputStream in = ; // Set this to the InputStream from HTTP as your provided example
    byte[] buffer = new byte[1024]; // You will need a small buffer mem though
    int len;
    while ((len = in.read(buffer)) != -1) {
        out.write(buffer, 0, len);
    }
    in.close();
    out.flush();
}



回答2:


Ok , I have solved my problem . I attach the solution . Maybe it's useful to anybody.

Controller

@RequestMapping(value="/eutm/{trademarkId}/snapshots/{historyId}/attachements/{attachementId}", method = RequestMethod.GET)
@ResponseBody
public void getTrademarkAttachement(HttpServletResponse response, @PathVariable String trademarkId, @PathVariable String historyId, @PathVariable String attachementId) {
    try {
        registerService.getTrademarkAttachement(trademarkId, historyId, attachementId, LanguageController.getLocale(), response.getOutputStream());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Service

 @Override
 public void getTrademarkAttachement(String trademarkId, String historyId, String attachementId, Locale locale, ServletOutputStream outputStream) {
    URI uri = loadHistoryUri(generateUri(REGISTER_BASE_MS_URL, REGISTER_HISTORY_ENTRY_TM_ATTACHEMENT_WS_URL, trademarkId, historyId, attachementId), locale.getLanguage());
    HttpURLConnection httpConn = null;
    String line = null;
    InputStream ins = null;
    try {
        httpConn = (HttpURLConnection) new URL(uri.toString()).openConnection();
        ins = httpConn.getInputStream();
        BufferedReader is = new BufferedReader(new InputStreamReader(ins));

        while ((line = is.readLine()) != null) {
            outputStream.write(line.getBytes());
        }
     outputStream.flush();
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        httpConn.disconnect();

        if(ins != null){
        try {
            ins.close();
        } catch (IOException e) {
            logger.error("Bad close of inputStream ins");
        }
        }
    }
}

This way, as it reads lines from inputStream ( url to retrieve via GET connection ), it writes it directly to the response via outputStream . It doesn't send bit to bit as in reactive mode , so the user is not getting the info directly, but I think that with Spring MVC 3.2 and Java 7 is the most approximate way to avoid elements in memory .



来源:https://stackoverflow.com/questions/59984666/read-a-resource-from-url-and-return-directly-those-bytes-as-response-of-rest-req

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!