リビジョン | 1543 (tree) |
---|---|
日時 | 2018-02-09 14:42:21 |
作者 | takahashi_m |
(メッセージはありません)
@@ -1,4 +1,12 @@ | ||
1 | -5.9.29.0 (2018/02/02) | |
1 | +5.9.29.1 (2018/02/09) | |
2 | + [Azureのストレージ対応] | |
3 | + 以前、bluemixのオブジェクトストレージに対応しましたが、Azureにも対応しておきます。 | |
4 | + なお、pluginを利用する際には追加で次の3つのjarファイルが必要です。 | |
5 | + azure-keyvault-core-0.8.0.jar,azure-storage-6.1.0.jar,commons-lang3-3.4.jar | |
6 | + hayabusa.servlet.FileDownload#doPost( final HttpServletRequest request, final HttpServletResponse response ) | |
7 | + plugin.cloud.StorageAPI_azure | |
8 | + | |
9 | +5.9.29.0 (2018/02/02) | |
2 | 10 | [ファイルのマルチバイト文字対応] |
3 | 11 | サーブレットの対応は行っていましたが、forwardタグ側の対応が漏れていたので追加します。(Edge,safari対応) |
4 | 12 | hayabusa.taglib.ForwardTag#doEndTag() |
@@ -18,6 +18,7 @@ | ||
18 | 18 | import java.io.FileInputStream; |
19 | 19 | import java.io.IOException; |
20 | 20 | import java.io.InputStream; |
21 | +import java.util.Map; | |
21 | 22 | |
22 | 23 | import javax.mail.internet.MimeUtility; |
23 | 24 | import javax.servlet.ServletException; |
@@ -69,19 +70,21 @@ | ||
69 | 70 | * |
70 | 71 | * 一般には、http://:ポート/システムID/jsp/fileDownload?file=サーバー物理ファイル&name=ファイル名 |
71 | 72 | * 形式のURL でアクセスします。 |
72 | - * | |
73 | + * | |
73 | 74 | * 5.9.25.0 (2017/10/06) |
74 | 75 | * クラウド上のPaaSでオブジェクトストレージを利用する際は以下のシステムリソースを設定してください。 |
75 | 76 | * CLOUD_STORAGE,CLOUD_STORAGE_CONTAINER |
76 | 77 | * plugin/cloud内のクラスを利用してファイルアップロード(FileUploadタグ)、ダウンロード(FileDownloadサーブレット)をAPI経由で行います。 |
77 | 78 | * プラグインが利用するjarファイルの配置は必要です。 |
78 | - * | |
79 | 79 | * |
80 | + * | |
80 | 81 | * forwardでアクセスする場合はファイル名の文字コード変換が不要なため、useStringConvert=falseの |
81 | 82 | * 引数を与えてください。(falseとしない場合は日本語ファイル名等でエラーが発生します) |
82 | 83 | * |
83 | 84 | * @og.rev 3.8.1.1 (2005/11/21) 新規追加 |
84 | 85 | * @og.rev 5.9.25.0 (2017/10/06) クラウド対応 |
86 | + * @og.rev 5.9.29.1 (2018/02/07) Azure対応追加 | |
87 | + * | |
85 | 88 | * @og.group その他機能 |
86 | 89 | * |
87 | 90 | * @version 0.9.0 2000/10/17 |
@@ -145,7 +148,8 @@ | ||
145 | 148 | * @og.rev 5.9.25.0 (2017/10/06) クラウドストレージからダウンロード処理を追加対応 |
146 | 149 | * @og.rev 5.9.27.0 (2017/12/01) Content-Lengthをhttpヘッダに追加しておく |
147 | 150 | * @og.rev 5.9.27.2 (2017/12/15) Edgeの日本語ファイル名対応 |
148 | - * @og.rev 5.9.28.1 (2018/01/19) safariの日本語ファイル名対応(最新のブラウザではRFC6266がとれるはず) | |
151 | + * @og.rev 5.9.28.1 (2018/01/19) safariの日本語ファイル名対応(RFC6266方式を併記) | |
152 | + * @og.rev 5.9.29.1 (2018/02/07) lengthのクラウド対応 | |
149 | 153 | * |
150 | 154 | * @param request HttpServletRequestオブジェクト |
151 | 155 | * @param response HttpServletResponseオブジェクト |
@@ -187,7 +191,6 @@ | ||
187 | 191 | |
188 | 192 | // 2017/10/06 ADD reqFilenameの保存 |
189 | 193 | String cloudFilename = reqFilename; |
190 | - | |
191 | 194 | // 5.3.5.0 (2011/05/01) ファイルダウンロードチェックキー対応 |
192 | 195 | boolean useCheck = HybsSystem.sysBool( "USE_FILEDOWNLOAD_CHECKKEY" ); |
193 | 196 | if( useCheck ) { |
@@ -234,7 +237,7 @@ | ||
234 | 237 | // } |
235 | 238 | |
236 | 239 | newFilenameEnc = StringUtil.urlEncode( newFilename ); // 5.9.28.1 (2018/01/19) |
237 | - | |
240 | + | |
238 | 241 | // 5.7.1.2 (2013/12/20) 条件を反転させた上でIE11対応を行う |
239 | 242 | // 5.9.27.2 (2017/12/15) EdgeもIE同様の処理にする |
240 | 243 | if( request.getHeader( "User-Agent" ).indexOf( "MSIE" ) >= 0 || request.getHeader( "User-Agent" ).indexOf( "Trident" ) >= 0 |
@@ -251,7 +254,7 @@ | ||
251 | 254 | // response.setHeader( "Content-disposition", "attachment; filename=\"" + newFilename + "\"" ); |
252 | 255 | // response.setHeader( "Content-disposition", dipositionType + "; filename=\"" + newFilename + "\"" ); |
253 | 256 | response.setHeader( "Content-disposition", dipositionType + "; filename=\"" + newFilename + "\"; " |
254 | - + "filename*=UTF-8''" + newFilenameEnc ); // 5.9.28.1 (2018/01/19) | |
257 | + + "filename*=UTF-8''" + newFilenameEnc ); // 5.9.28.1 (2018/01/19) RFC6266方式を併記 | |
255 | 258 | |
256 | 259 | // 5.3.4.0 (2011/04/01) IEでファイルが正しくダウンロードできないバグを修正 |
257 | 260 | response.setHeader( "Cache-Control", "public" ); |
@@ -261,20 +264,29 @@ | ||
261 | 264 | ServletOutputStream out = null; |
262 | 265 | // 2017/10/06 MODIFY bluemixのストレージ利用の処理を追加 |
263 | 266 | InputStream is = null; |
267 | + // 5.9.29.1 (2018/02/07) lengthのクラウド対応 | |
268 | + String filesize = null; | |
264 | 269 | try { |
265 | 270 | // 2017/10/06 ADD bluemixのストレージに保存する場合の処理を追加 |
266 | 271 | if(cloudFlag){ |
267 | 272 | HttpSession hsession = request.getSession(true); |
268 | 273 | StorageAPI storageApi = StorageAPIFactory.newStorageAPI(storage, HybsSystem.sys("CLOUD_STORAGE_CONTAINER"), hsession); |
274 | + // ストリームの取得 | |
269 | 275 | is = storageApi.get(cloudFilename, hsession); |
276 | + | |
277 | + // ファイルサイズを取得 | |
278 | + Map<String,String> map = storageApi.getInfo(cloudFilename, hsession); | |
279 | + filesize = map.get(StorageAPI.FILEINFO_SIZE); | |
270 | 280 | }else{ |
271 | 281 | // 標準のファイル保存 |
272 | 282 | fin = new FileInputStream( reqFilename ); |
273 | 283 | is = fin; |
284 | + filesize = String.valueOf(fin.available()); | |
274 | 285 | } |
275 | - | |
276 | - response.setHeader( "Content-Length", String.valueOf(fin.available()) ); // 5.9.27.0 (2017/12/01) | |
277 | 286 | |
287 | +// response.setHeader( "Content-Length", String.valueOf(fin.available()) ); // 5.9.27.0 (2017/12/01) | |
288 | + response.setHeader( "Content-Lnegth", filesize); // クラウドのサイズ取得対応 | |
289 | + | |
278 | 290 | out = response.getOutputStream(); |
279 | 291 | |
280 | 292 | // ファイル読み込み用バッファ |
@@ -0,0 +1,309 @@ | ||
1 | +package org.opengion.plugin.cloud; | |
2 | + | |
3 | +import java.io.InputStream; | |
4 | +import java.text.SimpleDateFormat; | |
5 | +import java.util.ArrayList; | |
6 | +import java.util.HashMap; | |
7 | +import java.util.List; | |
8 | +import java.util.Map; | |
9 | + | |
10 | +import javax.servlet.http.HttpSession; | |
11 | + | |
12 | +import org.opengion.fukurou.util.Closer; | |
13 | +import org.opengion.fukurou.util.FileUtil; | |
14 | +import org.opengion.fukurou.util.StringUtil; | |
15 | +import org.opengion.hayabusa.common.HybsSystem; | |
16 | +import org.opengion.hayabusa.common.HybsSystemException; | |
17 | +import org.opengion.hayabusa.io.StorageAPI; | |
18 | + | |
19 | +import com.microsoft.azure.storage.CloudStorageAccount; | |
20 | +import com.microsoft.azure.storage.blob.BlobOutputStream; | |
21 | +import com.microsoft.azure.storage.blob.BlobProperties; | |
22 | +import com.microsoft.azure.storage.blob.CloudBlob; | |
23 | +import com.microsoft.azure.storage.blob.CloudBlobClient; | |
24 | +import com.microsoft.azure.storage.blob.CloudBlobContainer; | |
25 | +import com.microsoft.azure.storage.blob.CloudBlockBlob; | |
26 | +import com.microsoft.azure.storage.blob.ListBlobItem; | |
27 | + | |
28 | +/** | |
29 | + * azure用のクラウドストレージ操作実装 | |
30 | + * | |
31 | + * システムリソースのCLOUD_STORAGE_AZURE_KEYに、Azureのキー情報を登録する必要があります。 | |
32 | + * | |
33 | + * @og.group クラウド | |
34 | + * @og.rev 5.9.29.1 (2018/02/09) 新規作成 | |
35 | + * | |
36 | + * @version 5.0 | |
37 | + * @author T.OTA | |
38 | + * @sinse JDK7.0 | |
39 | + */ | |
40 | +public class StorageAPI_azure implements StorageAPI { | |
41 | + // 認証文字列 | |
42 | + private CloudBlobContainer blobContainer = null; | |
43 | + | |
44 | + public StorageAPI_azure(String container, HttpSession hsession){ | |
45 | + String storageConnectionString = HybsSystem.sys("CLOUD_STORAGE_AZURE_KEY"); | |
46 | + if(StringUtil.isNull(storageConnectionString)){ | |
47 | + String errMsg = "Azure用認証キーがシステムリソースに登録されていません。"; | |
48 | + throw new HybsSystemException(errMsg); | |
49 | + } | |
50 | + | |
51 | + try{ | |
52 | + CloudStorageAccount account = CloudStorageAccount.parse(storageConnectionString); | |
53 | + CloudBlobClient serviceClient = account.createCloudBlobClient(); | |
54 | + blobContainer = serviceClient.getContainerReference(container); | |
55 | + // コンテナが存在しない場合は作成する | |
56 | + blobContainer.createIfNotExists(); | |
57 | + }catch(Exception e){ | |
58 | + StringBuilder sbErrMsg = new StringBuilder(); | |
59 | + sbErrMsg.append("コンテナの作成に失敗しました。container:"); | |
60 | + sbErrMsg.append(container); | |
61 | + throw new HybsSystemException(sbErrMsg.toString()); | |
62 | + } | |
63 | + } | |
64 | + | |
65 | + /** | |
66 | + * アップロード | |
67 | + * | |
68 | + * @param partInputStream アップロード対象のストリーム | |
69 | + * @param updFolder アップロードフォルタ名 | |
70 | + * @param updFileName アップロードファイル名 | |
71 | + * @param hsession セッション | |
72 | + */ | |
73 | + @Override | |
74 | + public void add(InputStream partInputStream, String updFolder, String updFileName, HttpSession hsession) { | |
75 | + BlobOutputStream blobOutputStream = null; | |
76 | + try { | |
77 | + // アップロード処理 | |
78 | + CloudBlockBlob blob = blobContainer.getDirectoryReference(updFolder).getBlockBlobReference(updFileName); | |
79 | + blobOutputStream = blob.openOutputStream(); | |
80 | + | |
81 | + byte buffer[] = new byte[4096]; | |
82 | + int size; | |
83 | + | |
84 | + while((size = partInputStream.read(buffer)) != -1){ | |
85 | + blobOutputStream.write(buffer,0,size); | |
86 | + blobOutputStream.flush(); | |
87 | + } | |
88 | + | |
89 | + } catch (Exception e) { | |
90 | + StringBuilder sbErrMsg = new StringBuilder(); | |
91 | + sbErrMsg.append("ストレージへのファイルアップロードに失敗しました。updFolder:"); | |
92 | + sbErrMsg.append(updFolder); | |
93 | + sbErrMsg.append(" updFileName:"); | |
94 | + sbErrMsg.append(updFileName); | |
95 | + sbErrMsg.append(" errInfo:"); | |
96 | + sbErrMsg.append(e); | |
97 | + throw new HybsSystemException(sbErrMsg.toString()); | |
98 | + } finally { | |
99 | + // クローズ処理 | |
100 | + Closer.ioClose(blobOutputStream); | |
101 | + Closer.ioClose(partInputStream); | |
102 | + } | |
103 | + } | |
104 | + | |
105 | + /** | |
106 | + * ダウンロード | |
107 | + * | |
108 | + * @param filePath ダウンロード対象のファイルパス | |
109 | + * @param hsession セッション | |
110 | + * @return ストリーム | |
111 | + */ | |
112 | + @Override | |
113 | + public InputStream get(String filePath, HttpSession hsession) { | |
114 | + CloudBlockBlob blob = null; | |
115 | + InputStream is = null; | |
116 | + // ダウンロード | |
117 | + try { | |
118 | + blob = blobContainer.getBlockBlobReference(filePath); | |
119 | + is = blob.openInputStream(); | |
120 | + } catch (Exception e) { | |
121 | + StringBuilder sbErrMsg = new StringBuilder(); | |
122 | + sbErrMsg.append("ストレージからのファイルダウンロードに失敗しました。filePath:"); | |
123 | + sbErrMsg.append(filePath); | |
124 | + sbErrMsg.append(" errInfo:"); | |
125 | + sbErrMsg.append(e); | |
126 | + throw new HybsSystemException(sbErrMsg.toString()); | |
127 | + } | |
128 | + | |
129 | + return is; | |
130 | + } | |
131 | + | |
132 | + /** | |
133 | + * コピー | |
134 | + * | |
135 | + * @param oldFilePath コピー元ファイルパス | |
136 | + * @param newFilePath コピー先ファイルパス | |
137 | + * @param hsession セッション | |
138 | + */ | |
139 | + @Override | |
140 | + public void copy(String oldFilePath, String newFilePath, HttpSession hsession) { | |
141 | + // コピー処理 | |
142 | + InputStream is = null; | |
143 | + | |
144 | + try { | |
145 | + CloudBlockBlob oldblob = blobContainer.getBlockBlobReference(oldFilePath); | |
146 | + CloudBlockBlob newblob = blobContainer.getBlockBlobReference(newFilePath); | |
147 | + newblob.startCopy(oldblob); | |
148 | + } catch (Exception e) { | |
149 | + StringBuilder sbErrMsg = new StringBuilder(); | |
150 | + sbErrMsg.append("ストレージのファイルコピー処理に失敗しました。oldFilePath:"); | |
151 | + sbErrMsg.append(oldFilePath); | |
152 | + sbErrMsg.append(" newFilePath:"); | |
153 | + sbErrMsg.append(newFilePath); | |
154 | + sbErrMsg.append(" errInfo:"); | |
155 | + sbErrMsg.append(e); | |
156 | + throw new HybsSystemException(sbErrMsg.toString()); | |
157 | + }finally{ | |
158 | + // クローズ処理 | |
159 | + Closer.ioClose(is); | |
160 | + } | |
161 | + } | |
162 | + | |
163 | + /** | |
164 | + * 削除 | |
165 | + * | |
166 | + * @param filePath 削除ファイルのパス | |
167 | + * @param hsession セッション | |
168 | + */ | |
169 | + @Override | |
170 | + public void delete(String filePath, HttpSession hsession) { | |
171 | + // 削除 | |
172 | + try { | |
173 | + CloudBlockBlob blob = blobContainer.getBlockBlobReference(filePath); | |
174 | + blob.delete(); | |
175 | + } catch (Exception e) { | |
176 | + StringBuilder sbErrMsg = new StringBuilder(); | |
177 | + sbErrMsg.append("ストレージのファイル削除に失敗しました。filePath:"); | |
178 | + sbErrMsg.append(filePath); | |
179 | + sbErrMsg.append(" errInfo:"); | |
180 | + sbErrMsg.append(e); | |
181 | + throw new HybsSystemException(sbErrMsg.toString()); | |
182 | + } | |
183 | + } | |
184 | + | |
185 | + /** | |
186 | + * ファイル名変更 | |
187 | + * | |
188 | + * @param filePath ファイルパス | |
189 | + * @param oldFileName 変更前ファイル名 | |
190 | + * @param newFileName 変更後ファイル名 | |
191 | + * @param useBackup 変更後ファイル名が既に存在する場合のバックアップ作成フラグ | |
192 | + * @param hsession セッション | |
193 | + */ | |
194 | + public void rename(String filePath, String oldFileName, String newFileName, final boolean useBackup, | |
195 | + HttpSession hsession) { | |
196 | + String newFilePath = filePath + newFileName; | |
197 | + String oldFilePath = filePath + oldFileName; | |
198 | + | |
199 | + // 変更先のファイルが存在した場合の処理 | |
200 | + if (exists(newFilePath, hsession)) { | |
201 | + // バックアップ作成する場合 | |
202 | + if (useBackup) { | |
203 | + // バックアップファイル名は、元のファイル名(拡張子含む) + "_" + 現在時刻のlong値 + "." + | |
204 | + // 元のファイルの拡張子 | |
205 | + String bkupPath = filePath + "_backup/" + newFileName + "_" + System.currentTimeMillis() | |
206 | + + FileUtil.EXTENSION_SEPARATOR + FileUtil.getExtension(newFileName); | |
207 | + // バックアップフォルダに移動 | |
208 | + copy(newFilePath, bkupPath, hsession); | |
209 | + } | |
210 | + } | |
211 | + | |
212 | + // コピー | |
213 | + copy(oldFilePath, newFilePath, hsession); | |
214 | + // 削除 | |
215 | + delete(oldFilePath, hsession); | |
216 | + } | |
217 | + | |
218 | + /** | |
219 | + * ファイル存在チェック | |
220 | + * | |
221 | + * @param filePath ファイルパス | |
222 | + * @param hsession セッション | |
223 | + * @return true:存在 false:存在しない | |
224 | + */ | |
225 | +// @Override | |
226 | + public boolean exists(String filePath, HttpSession hsession) { | |
227 | + boolean blnRtn = true; | |
228 | + try { | |
229 | + CloudBlockBlob blob = blobContainer.getBlockBlobReference(filePath); | |
230 | + if (!blob.exists()) { | |
231 | + // ファイルが取得できなかった場合は、falseを設定 | |
232 | + blnRtn = false; | |
233 | + } | |
234 | + } catch (Exception e) { | |
235 | + StringBuilder sbErrMsg = new StringBuilder(); | |
236 | + sbErrMsg.append("ストレージのファイル取得に失敗しました。filePath:"); | |
237 | + sbErrMsg.append(filePath); | |
238 | + sbErrMsg.append(" errInfo:"); | |
239 | + sbErrMsg.append(e); | |
240 | + throw new HybsSystemException(sbErrMsg.toString()); | |
241 | + } | |
242 | + | |
243 | + return blnRtn; | |
244 | + } | |
245 | + | |
246 | + /** | |
247 | + * ファイル一覧取得 | |
248 | + * | |
249 | + * @param startsWith パスの前方一致 | |
250 | + * @param hsession セッション | |
251 | + * @return ファイルパス一覧 | |
252 | + */ | |
253 | + @Override | |
254 | + public String[] list(String startsWith, HttpSession hsession) { | |
255 | + // 認証 | |
256 | + List<String> rtnList = new ArrayList<String>(); | |
257 | + try{ | |
258 | + // 一覧の取得 | |
259 | + for(ListBlobItem item: blobContainer.listBlobs(startsWith)){ | |
260 | + if(item instanceof CloudBlob){ | |
261 | + // 名称を格納 | |
262 | + rtnList.add(((CloudBlob)item).getName()); | |
263 | + } | |
264 | + } | |
265 | + } catch (Exception e){ | |
266 | + StringBuilder sbErrMsg = new StringBuilder(); | |
267 | + sbErrMsg.append("ファイル一覧の取得に失敗しました。startsWith:"); | |
268 | + sbErrMsg.append(startsWith); | |
269 | + sbErrMsg.append(" errInfo:"); | |
270 | + sbErrMsg.append("e"); | |
271 | + throw new HybsSystemException(sbErrMsg.toString()); | |
272 | + } | |
273 | + return rtnList.toArray(new String[rtnList.size()]); | |
274 | + } | |
275 | + | |
276 | + /** | |
277 | + * ファイル情報取得 | |
278 | + * | |
279 | + * @param path ファイルパス | |
280 | + * @param hsession セッション | |
281 | + * @return ファイル情報格納Map | |
282 | + */ | |
283 | +// @Override | |
284 | + public Map<String, String> getInfo(String path, HttpSession hsession) { | |
285 | + Map<String, String> rtnMap = new HashMap<String,String>(); | |
286 | + | |
287 | + CloudBlob blob = null; | |
288 | + try{ | |
289 | + // ファイルオブジェクトの取得 | |
290 | + blob = blobContainer.getBlobReferenceFromServer(path); | |
291 | + }catch(Exception e){ | |
292 | + StringBuilder sbErrMsg = new StringBuilder(); | |
293 | + sbErrMsg.append("ファイルの取得に失敗しました。path:"); | |
294 | + sbErrMsg.append(path); | |
295 | + sbErrMsg.append(" errInfo:"); | |
296 | + sbErrMsg.append(e); | |
297 | + throw new HybsSystemException(sbErrMsg.toString()); | |
298 | + } | |
299 | + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss"); | |
300 | + | |
301 | + BlobProperties properties = blob.getProperties(); | |
302 | + // ファイルサイズ | |
303 | + rtnMap.put(FILEINFO_SIZE, String.valueOf(properties.getLength())); | |
304 | + // 最終更新時刻 | |
305 | + rtnMap.put(FILEINFO_LASTMODIFIED, sdf.format(properties.getLastModified())); | |
306 | + | |
307 | + return rtnMap; | |
308 | + } | |
309 | +} |