2016-04-09 7 views
0

Fine UploaderとS3を使っている人は誰ですか?ファインアップローダ - Java Enpoint

ファインアップローダを使用してAWS S3に直接ファイルを送信しようとしています。エンドポイントサーブレットに問題があるか、クライアント側でサーブレットを設定していると思います。

[Fine Uploader 5.6.0]サーバーから空または無効な応答を受信しました。 [Fine Uploader 5.6.0]ポリシーに署名できませんでした。サーバーから空または無効な応答を受信しました。

Tksです。

マイエンドポイント:サーブレットUploadfiles - http://www.example.com/uploadfiles

import com.amazonaws.auth.AWSCredentials; 
import com.amazonaws.auth.BasicAWSCredentials; 
import com.amazonaws.services.s3.AmazonS3; 
import com.amazonaws.services.s3.AmazonS3Client; 
import com.amazonaws.util.BinaryUtils; 
import com.google.gson.JsonArray; 
import com.google.gson.JsonElement; 
import com.google.gson.JsonObject; 
import com.google.gson.JsonParser; 

import org.apache.commons.codec.binary.Hex; 

import javax.crypto.Mac; 
import javax.crypto.spec.SecretKeySpec; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

import java.io.IOException; 
import java.io.UnsupportedEncodingException; 
import java.security.InvalidKeyException; 
import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

@SuppressWarnings("serial") 
public class S3UploadsServlet extends HttpServlet 
{ 

    final static String AWS_SECRET_KEY = "MY_SECRET_KEY"; 
    final static String AWS_PUBLIC_KEY = "MY_PUBLIC_KEY"; 

    // Main entry point for POST requests from Fine Uploader. This currently assumes delete file requests use the 
    // default method of DELETE, but that can be adjusted. 
    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException 
    { 
     if (req.getServletPath().endsWith("s3/signature")) 
     { 
      handleSignatureRequest(req, resp); 
     } 
     else if (req.getServletPath().endsWith("s3/success")) 
     { 
      handleUploadSuccessRequest(req, resp); 
     } 
    } 

    // Main entry point for DELETE requests sent by Fine Uploader. 
    @Override 
    public void doDelete(HttpServletRequest req, HttpServletResponse resp) throws IOException 
    { 
     String key = req.getParameter("key"); 
     String bucket = req.getParameter("bucket"); 

     resp.setStatus(200); 

     AWSCredentials myCredentials = new BasicAWSCredentials(AWS_PUBLIC_KEY, AWS_SECRET_KEY); 
     AmazonS3 s3Client = new AmazonS3Client(myCredentials); 
     s3Client.deleteObject(bucket, key); 
    } 

    // Called by the main POST request handler if Fine Uploader has asked for an item to be signed. The item may be a 
    // policy document or a string that represents multipart upload request headers. 
    private void handleSignatureRequest(HttpServletRequest req, HttpServletResponse resp) throws IOException 
    { 
     resp.setStatus(200); 

     JsonParser jsonParser = new JsonParser(); 
     JsonElement contentJson = jsonParser.parse(req.getReader()); 
     JsonObject jsonObject = contentJson.getAsJsonObject(); 

     if (req.getQueryString() != null && req.getQueryString().contains("v4=true")) { 
      handleV4SignatureRequest(jsonObject, contentJson, req, resp); 
     } 
     else { 
      handleV2SignatureRequest(jsonObject, contentJson, req, resp); 
     } 

     resp.setStatus(200); 
    } 

    private void handleV2SignatureRequest(JsonObject payload, JsonElement contentJson, HttpServletRequest req, HttpServletResponse resp) throws IOException{ 
     String signature; 
     JsonElement headers = payload.get("headers"); 
     JsonObject response = new JsonObject(); 

     try 
     { 
      // If this is not a multipart upload-related request, Fine Uploader will send a policy document 
      // as the value of a "policy" property in the request. In that case, we must base-64 encode 
      // the policy document and then sign it. The will include the base-64 encoded policy and the signed policy document. 
      if (headers == null) 
      { 
       String base64Policy = base64EncodePolicy(contentJson); 
       signature = sign(base64Policy); 

       // Validate the policy document to ensure the client hasn't tampered with it. 
       // If it has been tampered with, set this property on the response and set the status to a non-200 value. 
       //response.addProperty("invalid", true); 

       response.addProperty("policy", base64Policy); 
      } 

      // If this is a request to sign a multipart upload-related request, we only need to sign the headers, 
      // which are passed as the value of a "headers" property from Fine Uploader. In this case, 
      // we only need to return the signed value. 
      else 
      { 
       signature = sign(headers.getAsString()); 
      } 

      response.addProperty("signature", signature); 
      resp.getWriter().write(response.toString()); 
     } 
     catch (Exception e) 
     { 
      resp.setStatus(500); 
     } 
    } 

    private void handleV4SignatureRequest(JsonObject payload, JsonElement contentJson, HttpServletRequest req, HttpServletResponse resp) throws IOException{ 
     String signature = null; 
     JsonElement headers = payload.get("headers"); 
     JsonObject response = new JsonObject(); 

     try 
     { 
      // If this is not a multipart upload-related request, Fine Uploader will send a policy document 
      // as the value of a "policy" property in the request. In that case, we must base-64 encode 
      // the policy document and then sign it. The will include the base-64 encoded policy and the signed policy document. 
      if (headers == null) 
      { 
       String base64Policy = base64EncodePolicy(contentJson); 
       JsonArray conditions = payload.getAsJsonArray("conditions"); 
       String credentialCondition = null; 
       for (int i = 0; i < conditions.size(); i++) { 
        JsonObject condition = conditions.get(i).getAsJsonObject(); 
        JsonElement value = condition.get("x-amz-credential"); 
        if (value != null) { 
         credentialCondition = value.getAsString(); 
         break; 
        } 
       } 

       // Validate the policy document to ensure the client hasn't tampered with it. 
       // If it has been tampered with, set this property on the response and set the status to a non-200 value. 
//    response.addProperty("invalid", true); 


       Pattern pattern = Pattern.compile(".+\\/(.+)\\/(.+)\\/s3\\/aws4_request"); 
       Matcher matcher = pattern.matcher(credentialCondition); 
       matcher.matches(); 
       signature = getV4Signature(matcher.group(1), matcher.group(2), base64Policy); 

       response.addProperty("policy", base64Policy); 
      } 

      // If this is a request to sign a multipart upload-related request, we only need to sign the headers, 
      // which are passed as the value of a "headers" property from Fine Uploader. In this case, 
      // we only need to return the signed value. 
      else 
      { 
       Pattern pattern = Pattern.compile(".+\\n.+\\n(\\d+)\\/(.+)\\/s3\\/aws4_request\\n(.+)", Pattern.DOTALL); 
       Matcher matcher = pattern.matcher(headers.getAsString()); 
       matcher.matches(); 
       String canonicalRequest = matcher.group(3); 
       String hashedCanonicalRequest = hash256(canonicalRequest); 
       String stringToSign = headers.getAsString().replaceAll("(?s)(.+s3\\/aws4_request\\n).+", "$1" + hashedCanonicalRequest); 

       // Validate the policy document to ensure the client hasn't tampered with it. 
       // If it has been tampered with, set this property on the response and set the status to a non-200 value. 
       // response.addProperty("invalid", true); 

       signature = getV4Signature(matcher.group(1), matcher.group(2), stringToSign); 
      } 

      response.addProperty("signature", signature); 
      resp.getWriter().write(response.toString()); 
     } 
     catch (Exception e) 
     { 
      resp.setStatus(500); 
     } 
    } 

    // Called by the main POST request handler if Fine Uploader has indicated that the file has been 
    // successfully sent to S3. You have the opportunity here to examine the file in S3 and "fail" the upload 
    // if something in not correct. 
    private void handleUploadSuccessRequest(HttpServletRequest req, HttpServletResponse resp) { 
     String key = req.getParameter("key"); 
     String uuid = req.getParameter("uuid"); 
     String bucket = req.getParameter("bucket"); 
     String name = req.getParameter("name"); 

     resp.setStatus(200); 
     System.out.println(String.format("Upload successfully sent to S3! Bucket: %s, Key: %s, UUID: %s, Filename: %s", 
       bucket, key, uuid, name)); 
    } 

    private String getV4Signature(String date, String region, String stringToSign) throws Exception { 
     byte[] kSecret = ("AWS4" + AWS_SECRET_KEY).getBytes("UTF8"); 
     byte[] kDate = sha256Encode(date, kSecret); 
     byte[] kRegion = sha256Encode(region, kDate); 
     byte[] kService = sha256Encode("s3", kRegion); 
     byte[] kSigning = sha256Encode("aws4_request", kService); 
     byte[] kSignature = sha256Encode(stringToSign, kSigning); 
     return Hex.encodeHexString(kSignature); 
    } 

    private byte[] sha256Encode(String data, byte[] key) throws Exception { 
     String algorithm="HmacSHA256"; 
     Mac mac = Mac.getInstance(algorithm); 
     mac.init(new SecretKeySpec(key, algorithm)); 
     return mac.doFinal(data.getBytes("UTF8")); 
    } 

    private String hash256(String data) throws NoSuchAlgorithmException { 
     MessageDigest md = MessageDigest.getInstance("SHA-256"); 
     md.update(data.getBytes()); 
     return bytesToHex(md.digest()); 
    } 

    private String bytesToHex(byte[] bytes) { 
     StringBuffer result = new StringBuffer(); 
     for (byte byt : bytes) result.append(Integer.toString((byt & 0xff) + 0x100, 16).substring(1)); 
     return result.toString(); 
    } 

    private String base64EncodePolicy(JsonElement jsonElement) throws UnsupportedEncodingException{ 
     String policyJsonStr = jsonElement.toString(); 
     String base64Encoded = BinaryUtils.toBase64 (policyJsonStr.getBytes("UTF-8")); 
     return base64Encoded; 
    } 

    private String sign(String toSign) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException{ 
     Mac hmac = Mac.getInstance("HmacSHA1"); 
     hmac.init(new SecretKeySpec(AWS_SECRET_KEY.getBytes("UTF-8"), "HmacSHA1")); 
     String signature = BinaryUtils.toBase64 (hmac.doFinal(toSign.getBytes("UTF-8"))); 
     return signature; 
    } 
} 

私のJSPページ:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" 
    pageEncoding="ISO-8859-1"%> 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
    <meta charset="utf-8"> 
    <meta name="viewport" content="width=device-width, initial-scale=1"> 
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script> 
    <link href="/mysite/uploader/fine-uploader-gallery.css" rel="stylesheet"> 
    <script src="/mysite/uploader/s3.jquery.fine-uploader.js"></script> 
    <script type="text/template" id="qq-template-s3"> 
     <div class="qq-uploader-selector qq-uploader qq-gallery" qq-drop-area-text="Drop files here"> 
      <div class="qq-total-progress-bar-container-selector qq-total-progress-bar-container"> 
       <div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-total-progress-bar-selector qq-progress-bar qq-total-progress-bar"></div> 
      </div> 
      <div class="qq-upload-drop-area-selector qq-upload-drop-area" qq-hide-dropzone> 
       <span class="qq-upload-drop-area-text-selector"></span> 
      </div> 
      <div class="qq-upload-button-selector qq-upload-button"> 
       <div>Upload a file</div> 
      </div> 
      <span class="qq-drop-processing-selector qq-drop-processing"> 
       <span>Processing dropped files...</span> 
       <span class="qq-drop-processing-spinner-selector qq-drop-processing-spinner"></span> 
      </span> 
      <ul class="qq-upload-list-selector qq-upload-list" role="region" aria-live="polite" aria-relevant="additions removals"> 
       <li> 
        <span role="status" class="qq-upload-status-text-selector qq-upload-status-text"></span> 
        <div class="qq-progress-bar-container-selector qq-progress-bar-container"> 
         <div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-progress-bar-selector qq-progress-bar"></div> 
        </div> 
        <span class="qq-upload-spinner-selector qq-upload-spinner"></span> 
        <div class="qq-thumbnail-wrapper"> 
         <a class="preview-link" target="_blank"> 
          <img class="qq-thumbnail-selector" qq-max-size="120" qq-server-scale> 
         </a> 
        </div> 
        <button type="button" class="qq-upload-cancel-selector qq-upload-cancel">X</button> 
        <button type="button" class="qq-upload-retry-selector qq-upload-retry"> 
         <span class="qq-btn qq-retry-icon" aria-label="Retry"></span> 
         Retry 
        </button> 

        <div class="qq-file-info"> 
         <div class="qq-file-name"> 
          <span class="qq-upload-file-selector qq-upload-file"></span> 
          <span class="qq-edit-filename-icon-selector qq-edit-filename-icon" aria-label="Edit filename"></span> 
         </div> 
         <input class="qq-edit-filename-selector qq-edit-filename" tabindex="0" type="text"> 
         <span class="qq-upload-size-selector qq-upload-size"></span> 
         <button type="button" class="qq-btn qq-upload-delete-selector qq-upload-delete"> 
          <span class="qq-btn qq-delete-icon" aria-label="Delete"></span> 
         </button> 
         <button type="button" class="qq-btn qq-upload-pause-selector qq-upload-pause"> 
          <span class="qq-btn qq-pause-icon" aria-label="Pause"></span> 
         </button> 
         <button type="button" class="qq-btn qq-upload-continue-selector qq-upload-continue"> 
          <span class="qq-btn qq-continue-icon" aria-label="Continue"></span> 
         </button> 
        </div> 
       </li> 
      </ul> 

      <dialog class="qq-alert-dialog-selector"> 
       <div class="qq-dialog-message-selector"></div> 
       <div class="qq-dialog-buttons"> 
        <button type="button" class="qq-cancel-button-selector">Close</button> 
       </div> 
      </dialog> 

      <dialog class="qq-confirm-dialog-selector"> 
       <div class="qq-dialog-message-selector"></div> 
       <div class="qq-dialog-buttons"> 
        <button type="button" class="qq-cancel-button-selector">No</button> 
        <button type="button" class="qq-ok-button-selector">Yes</button> 
       </div> 
      </dialog> 

      <dialog class="qq-prompt-dialog-selector"> 
       <div class="qq-dialog-message-selector"></div> 
       <input type="text"> 
       <div class="qq-dialog-buttons"> 
        <button type="button" class="qq-cancel-button-selector">Cancel</button> 
        <button type="button" class="qq-ok-button-selector">Ok</button> 
       </div> 
      </dialog> 
     </div> 
    </script> 

    <style> 
     #fine-uploader-s3 .preview-link { 
      display: block; 
      height: 100%; 
      width: 100%; 
     } 
    </style> 

    <title>Fine Uploader S3 Demo</title> 
</head> 
<body> 

    <div id="fine-uploader-s3"></div> 

    <script> 
     $('#fine-uploader-s3').fineUploaderS3({ 
       debug: true, 
      template: 'qq-template-s3', 
      request: { 
       endpoint: "my_bucket.s3.amazonaws.com", 
       accessKey: "my_access_key" 
      }, 
      signature: { 
       endpoint: "http://www.example.com/uploadfiles" 
      }, 
      uploadSuccess: { 
       endpoint: "http://www.example.com/uploadfiles?success", 
       params: { 
        isBrowserPreviewCapable: qq.supportedFeatures.imagePreviews 
       } 
      }, 
      iframeSupport: { 
       localBlankPagePath: "/server/success.html" 
      }, 
      cors: { 
       expected: false 
      }, 
      chunking: { 
       enabled: true 
      }, 
      resume: { 
       enabled: true 
      }, 
      deleteFile: { 
       enabled: true, 
       method: "POST", 
       endpoint: "http://www.example.com/uploadfiles" 
      }, 
      validation: { 
       itemLimit: 5, 
       sizeLimit: 15000000 
      }, 
      thumbnails: { 
       placeholders: { 
        notAvailablePath: "/uploader/placeholders/not_available-generic.png", 
        waitingPath: "/uploader/placeholders/waiting-generic.png" 
       } 
      }, 
      callbacks: { 
       onComplete: function(id, name, response) { 
        var previewLink = qq(this.getItemByFileId(id)).getByClass('preview-link')[0]; 

        if (response.success) { 
         previewLink.setAttribute("href", response.tempLink) 
        } 
       } 
      } 
     }); 
    </script> 
</body> 
</html> 
+1

実例はhttps://github.com/FineUploader/server-examplesにあります。コードに何が含まれているかを判断したら、回答を提供してください。あなたのコードを提供していないので誰も助けることはできません。 –

+0

こんにちは、あなたの返事のためのtks。 申し訳ありません。元の投稿で使用しているコードをご覧ください。 Tks。 –

+0

おそらく、サーバー構成の問題です。 _exact_レスポンスはブラウザによってどのように見えますか?すべてのヘッダーとレスポンスペイロードを含めてください。 –

答えて

1

答え:私はちょうどJSPでのエンドポイントURLを変更し

signature: { 
      endpoint: "http://www.mysite/uploadfiles?status=signature" 
      }, 
      uploadSuccess: { 
       endpoint: "http://www.mysite/uploadfiles?status=success", 
       params: { 
        isBrowserPreviewCapable: qq.supportedFeatures.imagePreviews 
       } 
      } 

およびサーブレットでの条件構造 - doPostメソッド:

public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { 
     if (req.getParameter("status").equals("signature")) 
      handleSignatureRequest(req, resp); 
     else if (req.getParameter("status").equals("success")) 
      handleUploadSuccessRequest(req, resp); 
    } 

は現在正常に動作します。

関連する問題