2015-11-09 16 views
8

アイデアダウンロードやSpringのWeb内の別のコントローラのアクションにエラーメッセージをリダイレクトMVC

  • がリモートからファイルをダウンロードします。私は、これらのtaksの一方または両方を達成する必要があります春のWeb MVCのアクションを持っていますサーバーを開き、入力ストリームを応答出力ストリームに書き込みます。
  • ダウンロードの例外をキャッチし、複数のエラーメッセージの1つを設定し、/ addressesページにリダイレクトします。アドレスページにエラーが表示されます問題

:春は、ファイルをダウンロードし、問題が発生した場合にリダイレクトすることができない - 何とかリダイレクトで迷子になるので、属性は動作しません点滅:

/アドレスの
@ResponseBody 
@RequestMapping(value = "/download/{fileaddress}", method = RequestMethod.GET) 
public void download(HttpServletRequest request, HttpServletResponse response, @PathVariable(value = "fileaddress") String fileaddress) throws Exception 
{ 
    if(fileaddress != null && fileaddress.length() > 0) 
    { 
     try 
     { 
      // Get the remove file based on the fileaddress 
      RemoteFile remotefile = new RemoteFile(fileaddress); 

      // Set the input stream 
      InputStream inputstream = remotefile.getInputStream(); 

      // Write the input stream to the output stream or throw an exception 
      Utils.writeTo(inputstream, response.getOutputStream()); 
     } 
     catch(MyExceptionA) 
     { 
      // TODO: Define error message a and pass it to /addresses 
      // PROBLEM: Flash attributes that contain all critical error information don't work 
      response.sendRedirect(request.getContextPath() + "/addresses"); 
     } 
     catch(MyExceptionB) 
     { 
      // TODO: Add another error message and redirect 
      response.sendRedirect(request.getContextPath() + "/addresses"); 
     } 
     catch(MyExceptionC) 
     { 
      // TODO: Add another error message and redirect 
      response.sendRedirect(request.getContextPath() + "/addresses"); 
     } 
     catch(MyExceptionN) 
     { 
      // TODO: Add another error message and redirect 
      response.sendRedirect(request.getContextPath() + "/addresses"); 
     } 
    } 
    else 
    { 
     // TODO: Add error message 
     response.sendRedirect(request.getContextPath() + "/addresses"); 
    } 
} 

JSPページ:

<%@ page pageEncoding="UTF-8" %> 
<%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %> 
<%@ taglib prefix="core" uri="http://java.sun.com/jsp/jstl/core" %> 

<tags:index> 
    <jsp:attribute name="content"> 
     <core:if test="${not empty error}"> 
      <div class="alert alert-danger"> 
       <p>${error}</p> 
      </div> 
     </core:if> 
     <p>Page under construction!</p> 
    </jsp:attribute> 
</tags:index> 

質問:私は(エラーメッセージを表示することができていますどのように単純な文字列など)は/ addressesサイトにありますか?異なるURLパラメータ(error = errora、error = errorb ...)を使用すると、複数のエラータイプがあり、GETパラメータがプロフェッショナルではなく、エンコーディングの問題の根源であるため、エラーメッセージを渡すと大きな苦痛があります。

答えて

7

RedirectAttributesコントローラは、リダイレクトのシナリオの属性を選択するために使用することができますModelの専門です。 だから作業例のコードの下に以下を参照してください

@ResponseBody 
@RequestMapping(value = "/download/{fileaddress}", method = RequestMethod.GET) 
public Object download(@PathVariable(value = "fileaddress") String fileaddress, RedirectAttributes redirectAttrs) throws Exception { 
    if(StringUtils.hasText(fileaddress)){ 
     try{ 
      // Get the remove file based on the fileaddress 
      RemoteFile remotefile = new RemoteFile(fileaddress); 

      // Set the input stream 
      InputStream inputstream = remotefile.getInputStream(); 
      // asume that it was a PDF file 
      HttpHeaders responseHeaders = new HttpHeaders(); 
      InputStreamResource inputStreamResource = new InputStreamResource(inputStream); 
      responseHeaders.setContentLength(contentLengthOfStream); 
      responseHeaders.setContentType(MediaType.valueOf("application/pdf")); 
      return new ResponseEntity<InputStreamResource> (inputStreamResource, 
             responseHeaders, 
             HttpStatus.OK); 
     } catch (MyExceptionA | MyExceptionB | MyExceptionC | MyExceptionD ex) { 
      redirectAttrs.addFlashAttribute("error", ex.getMessage()); 
     }   
    } else { 
     redirectAttrs.addFlashAttribute("error", "File name is required"); 
    } 
    return "redirect:/addresses"; 
} 
+0

IOUtils.toByteArray(inputstream)がファイルからメモリにすべてを読み込むので、これが問題になる可能性があります。ファイルが大きすぎる場合、その方法は機能しません。 – Kuvaldis

+0

私は同意しますが、ファイルをストリームする方法ではなく、 '' RedirectAttributes''についての質問です。D – Babl

+0

メモリの問題を修正するコード例を更新しました:) – Babl

1

私はそれがサーバーからファイルをダウンロードするが、あなたの2番目のクエリに来ていない理由について説明することはできません、あなたはのModelAndViewとして、あなたのメソッドの戻り値の型を取り、この

ModelAndView mav = new ModelAndView("write here your jsp page name even is will work for remote server"); 
     try { 
      mav.addObject("some key","here you can write any message that will you can show in your jsp page.."); 
のように行うのいずれか二つの方法でリダイレクトすることができます

その後、mavを返します。 このように、条件付きでいくつのページをリダイレクトすることができます。

と2番目のアプローチでは、メソッドの型Stringを返すことができ、必要なJSPに直接リダイレクトできます。

+0

問題が発生する可能性のある入力ストリームとしてダウンロードを表示するだけです(書き込みプロセス中に切断するなど)。問題は次のとおりです。出力ストリームに書き込むことはできません。問題が発生した場合はリダイレクトすることができます答えは本当に可能ではありません – swaechter

+0

また、入力ストリームから複数回読むことはできません – swaechter

1

アップデート:私は質問を考えたがそうでなければ、解決策は、(RedirectAttributesを使用)かなり明白であるため、RedirectAttributesが利用できない状況についてです。

のorignalの答え:私は春がRedirectAttributesをサポートしていない状況でフラッシュマップにメッセージをバインドするには、次のコードを使用してい

(例えばExceptionHandler方法で):

public static Feedback getInstance(HttpServletRequest request, HttpServletResponse response) throws IllegalArgumentException { 
    FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request); 
    Object o = flashMap.get(KEY); 
    if (o != null) { 
     if (o instanceof Feedback) { 
      return Feedback.class.cast(o); 
     } else { 
      throw new IllegalArgumentException(...); 
     } 
    } else { 
     FeedbackContainer feedbackContainer = new FeedbackContainer(); 
     flashMap.put(KEY, feedbackContainer); 
     FlashMapManager flashMapManager = RequestContextUtils.getFlashMapManager(request); 
     flashMapManager.saveOutputFlashMap(flashMap, request, response); 
     return feedbackContainer; 
    } 

ここでFeedback/FeedbackContainerはJSONのシリアル化によってJPSでアクセスされるメッセージのコンテナです。あなたのケースでは、「エラー」キーを単なる文字列を使用することができますし、JSPに直接アクセス:

void storeErrorMsg(HttpServletRequest request, HttpServletResponse response, String message) { 
    FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request); 
    flashMap.put("error", message); 
    FlashMapManager flashMapManager = RequestContextUtils.getFlashMapManager(request); 
    flashMapManager.saveOutputFlashMap(flashMap, request, response); 
} 

私自身のメッセージコンテナを使用する主な理由は、異なるレベルと追加して複数のメッセージを持っている可能性がありますgetInstanceのメソッドRedirectAttributesModelまたはModelMapのため、フィードバックバインディングやバインドコードが重複しているかどうかは気にしません。あなたが必要なもの

+0

ありがとうございましたが、完全な実例を提供する方法で質問を編集できますか?たとえば、KEYはどのように定義されていますか? – swaechter

+0

KEYは、フィードバックインスタンスを格納するために使用する文字列を含む定数です(例: "feedback"がメソッド 'getAll()'を定義している場合)を介してすべてのメッセージにアクセスすることができます。あなたの場合、それは単純に「エラー」ですが、あなたが望む任意の値を選ぶことができます。 – Robin

0

私は次のようなアプローチを示唆している:あなたは、例外が発生した時点からそれを読み取ることができない入力ストリームとして、いくつかのリモートファイルを持っているので を。したがって、ローカルホスト上の一時フォルダにファイルをダウンロードすることでエラーの可能性を減らすことができます。

ここでエラーが発生した場合は、提案どおりにリダイレクトするか、別の試行を行い、何回か失敗した後にリダイレクトすることができます。この方法では、ファイルが正常にダウンロードされるまでストリームに何も書き込まれません。

ファイルがサーバーにダウンロードされると、そのファイルをクライアントに渡すことができます。たとえば、バイトを読み込んで現在の位置を保存することができます。ストリームに書き込む途中で例外が発生したとします。途中から失敗した点からの書き込みを復元することができます。

小さな例

... 
    final String localFileName = saveFileLocally(fileaddress) 
    if (localFileName == null) { 
     response.sendRedirect(request.getContextPath() + "/addresses"); 
    } else { 
     safeWrite(new BufferedInputStream(new FileInputStream(new File(localFileName))), response.getOutputStream()); 
    } 
... 

safeWriteローカルファイルをサポートしている必要があり、ファイルの途中から読んで例外処理をお読みください。このような操作には標準のJava APIが必要です。

+0

のセキュリティ上の懸念があり、ダウンロード時間が倍増した場合、これは実際のオプションではありません。 – swaechter

関連する問題