「Java Windowsファイル共有サービス(CIFS)経由でファイルを書き込む」の版間の差分
ナビゲーションに移動
検索に移動
13行目: | 13行目: | ||
import java.io.FileOutputStream; | import java.io.FileOutputStream; | ||
import java.io.InputStream; | import java.io.InputStream; | ||
− | import java.net. | + | import java.net.MalformedU[[R]]LException; |
import jcifs.smb.SmbException; | import jcifs.smb.SmbException; | ||
33行目: | 33行目: | ||
/** | /** | ||
− | * 通常のファイルシステムもしくは CIFS( | + | * 通常のファイルシステムもしくは CIFS([[Windows]]ファイル共有サービス) にファイルを書き込む |
* | * | ||
* @param is 書き込み内容 | * @param is 書き込み内容 | ||
75行目: | 75行目: | ||
cisfPath(targetFile.getAbsolutePath()))); | cisfPath(targetFile.getAbsolutePath()))); | ||
− | } catch ( | + | } catch (MalformedU[[R]]LException e) { |
// TODO | // TODO | ||
} | } | ||
171行目: | 171行目: | ||
* @param user | * @param user | ||
* @param password | * @param password | ||
− | * @throws | + | * @throws MalformedU[[R]]LException |
* @throws SmbException | * @throws SmbException | ||
*/ | */ | ||
177行目: | 177行目: | ||
File dir, | File dir, | ||
String user, | String user, | ||
− | String password) throws | + | String password) throws MalformedU[[R]]LException, SmbException { |
SmbFile cifsDir = new SmbFile( | SmbFile cifsDir = new SmbFile( | ||
191行目: | 191行目: | ||
/** | /** | ||
− | * CIFS アクセス | + | * CIFS アクセス U[[R]]L |
* @param user | * @param user | ||
* @param password | * @param password | ||
201行目: | 201行目: | ||
} | } | ||
/** | /** | ||
− | * '@' is | + | * '@' is U[[R]]L encoded with the '%40' hexcode escape |
* | * | ||
* @param password | * @param password | ||
241行目: | 241行目: | ||
} | } | ||
} | } | ||
− | ===JAX-RS のプロバイダ例=== | + | ===[[JAX-RS]] のプロバイダ例=== |
− | *SmbFile を JAX-RS のレスポンスとして返すためのプロバイダ | + | *SmbFile を [[JAX-RS]] のレスポンスとして返すためのプロバイダ |
− | package info.typea. | + | package info.typea.pro[[vi]]der; |
import java.io.IOException; | import java.io.IOException; | ||
250行目: | 250行目: | ||
import java.lang.annotation.Annotation; | import java.lang.annotation.Annotation; | ||
import java.lang.reflect.Type; | import java.lang.reflect.Type; | ||
− | import java.security. | + | import java.security.[[Access]]Controller; |
− | import java.security. | + | import java.security.Pri[[vi]]legedActionException; |
− | import java.security. | + | import java.security.Pri[[vi]]legedExceptionAction; |
import javax.ws.rs.Consumes; | import javax.ws.rs.Consumes; | ||
260行目: | 260行目: | ||
import javax.ws.rs.core.MultivaluedMap; | import javax.ws.rs.core.MultivaluedMap; | ||
import javax.ws.rs.ext.MessageBodyWriter; | import javax.ws.rs.ext.MessageBodyWriter; | ||
− | import javax.ws.rs.ext. | + | import javax.ws.rs.ext.Pro[[vi]]der; |
import jcifs.smb.SmbException; | import jcifs.smb.SmbException; | ||
270行目: | 270行目: | ||
/** | /** | ||
− | * Windows ファイル共有 サービス(CIFS) ファイル 用 JAX-RS プロバイダー | + | * [[Windows]] ファイル共有 サービス(CIFS) ファイル 用 JAX-RS プロバイダー |
* | * | ||
− | * @see org.apache.wink.common.internal. | + | * @see org.apache.wink.common.internal.pro[[vi]]ders.entity.FilePro[[vi]]der |
*/ | */ | ||
− | @ | + | @Pro[[vi]]der |
@Produces({ "*/*" }) | @Produces({ "*/*" }) | ||
@Consumes({ "*/*" }) | @Consumes({ "*/*" }) | ||
− | public class | + | public class SmbFilePro[[vi]]der implements MessageBodyWriter<SmbFile> { |
− | private static final Logger logger = LoggerFactory.getLogger( | + | private static final Logger logger = LoggerFactory.getLogger(SmbFilePro[[vi]]der.class); |
@Override | @Override | ||
304行目: | 304行目: | ||
Annotation[] annotations, | Annotation[] annotations, | ||
MediaType mediaType, | MediaType mediaType, | ||
− | MultivaluedMap<String, Object> | + | MultivaluedMap<String, Object> http[[Header]]s, |
OutputStream entityStream) throws IOException, WebApplicationException { | OutputStream entityStream) throws IOException, WebApplicationException { | ||
311行目: | 311行目: | ||
final OutputStream os = entityStream; | final OutputStream os = entityStream; | ||
− | + | [[Access]]Controller.doPrivileged(new PrivilegedExceptionAction() { | |
public Object run() throws IOException { | public Object run() throws IOException { | ||
− | if ((!(smbFile. | + | if ((!(smbFile.can[[R]]ead())) || (smbFile.isDirectory())) { |
− | if ( | + | if (SmbFilePro[[vi]]der.logger.isWarnEnabled()) { |
− | + | SmbFilePro[[vi]]der.logger.error(String | |
− | .format(" | + | .format("cannotUseFileAs[[R]]esponse %s", smbFile.getPath())); |
} | } | ||
323行目: | 323行目: | ||
SmbFileInputStream fis = new SmbFileInputStream(smbFile); | SmbFileInputStream fis = new SmbFileInputStream(smbFile); | ||
try { | try { | ||
− | + | SmbFilePro[[vi]]der.this.pipe(fis, os); | |
} finally { | } finally { | ||
fis.close(); | fis.close(); | ||
331行目: | 331行目: | ||
} | } | ||
}); | }); | ||
− | } catch ( | + | } catch (Pri[[vi]]legedActionException e) { |
if (e.getException() instanceof IOException) | if (e.getException() instanceof IOException) | ||
throw ((IOException) e.getException()); | throw ((IOException) e.getException()); |
2020年2月16日 (日) 04:27時点における最新版
Java Windowsファイル共有サービス(CIFS)経由でファイルを書き込む
- アプリケーションサーバー等、サービスで動くアプリケーションは、ログインユーザーとは別権限で動作しており、ファイル共有されたドライブのファイル参照、書き出しが出来ない。
- JCIFSライブラリを利用して対応する
書き込みユーティリティ例
package info.typea.util; import java.io.BufferedInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.net.MalformedURLException; import jcifs.smb.SmbException; import jcifs.smb.SmbFile; import jcifs.smb.SmbFileOutputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * ファイルシステムユーティリティ * */ public class FileSystemUtils { protected static Logger logger = LoggerFactory.getLogger(FileSystemUtils.class); private static final int BUF_SIZE = 4096; private FileSystemUtils(){} /** * 通常のファイルシステムもしくは CIFS(Windowsファイル共有サービス) にファイルを書き込む * * @param is 書き込み内容 * @param file 書き込み対象ファイル * @param isCifs CIFS か否か * @return */ public static FileSystemUtilInfo writeToFile( InputStream is, File file, boolean isCifs, String user, String password) { if (isCifs) { return writeToCifsFile(is, file, user, password); } else { return writeToLocalFile(is, file); } } /** * java.io.File から、SmbFile オブジェクトを生成する * * @param targetFile * @param user * @param password * @return */ public static SmbFile createSmbFileFromFile( File targetFile, String user, String password) { SmbFile file = null; try { file = new SmbFile( cifsUrl( user, cisfPassword(password), cisfPath(targetFile.getAbsolutePath()))); } catch (MalformedURLException e) { // TODO } return file; } /** * 通常のファイルシステムにファイルを作成 * * @param is * @param targetFile * @return */ private static FileSystemUtilInfo writeToLocalFile(InputStream is, File targetFile) { FileSystemUtilInfo info = new FileSystemUtilInfo(); FileOutputStream fos = null; try { fos = new FileOutputStream(targetFile); BufferedInputStream bis = new BufferedInputStream(is); int len = 0; long fileSize = 0; byte[] buffer = new byte[BUF_SIZE]; while ((len = bis.read(buffer)) >= 0) { fos.write(buffer,0, len); fileSize += len; } info.setFileSize(fileSize); bis.close(); } catch(Exception e) { throw new IllegalStateException(e); } finally { try { fos.close(); } catch (Exception e2) {} } return info; } /** * CIFS ファイルシステムにファイルを作成 * * @param is * @param targetFile * @return * @see http://jcifs.samba.org/src/docs/api/jcifs/smb/SmbFile.html */ private static FileSystemUtilInfo writeToCifsFile( InputStream is, File targetFile, String user, String password) { FileSystemUtilInfo info = new FileSystemUtilInfo(); try { makeCifsDirectories(targetFile.getParentFile(), user, password); SmbFile file = new SmbFile( cifsUrl( user, cisfPassword(password), cisfPath(targetFile.getAbsolutePath()))); if (!file.exists()) { file.createNewFile(); } SmbFileOutputStream fos = new SmbFileOutputStream(file); BufferedInputStream bis = new BufferedInputStream(is); int len = 0; long fileSize = 0; byte[] buffer = new byte[BUF_SIZE]; while ((len = bis.read(buffer)) >= 0) { fos.write(buffer,0, len); fileSize += len; } info.setFileSize(fileSize); bis.close(); } catch (Exception e) { // TODO } return info; } /** * CIFS ディレクトリが存在しない場合、作成する * * @param dir * @param user * @param password * @throws MalformedURLException * @throws SmbException */ private static void makeCifsDirectories( File dir, String user, String password) throws MalformedURLException, SmbException { SmbFile cifsDir = new SmbFile( cifsUrl( user, cisfPassword(password), cisfPath(dir.getAbsolutePath()))); if (!cifsDir.exists()) { cifsDir.mkdirs(); } } /** * CIFS アクセス URL * @param user * @param password * @param path * @return */ private static String cifsUrl(String user, String password, String path) { return String.format("smb://%s:%s@%s",user,password,path); } /** * '@' is URL encoded with the '%40' hexcode escape * * @param password * @return */ private static String cisfPassword(String password) { return password.replaceAll("@", "%40"); } /** * "\\" で始まる、UNCパス を "server/share/path/to/file.txt" のような書式に変換 * * @param path * @return */ private static String cisfPath(String path) { // \\ を取り除く if (path.substring(0,2).equals("\\\\")) { path = path.substring(2); } return path.replaceAll("\\\\", "\\/"); } /** * 結果情報 * */ public static class FileSystemUtilInfo { private long fileSize; public long getFileSize() { return fileSize; } public void setFileSize(long fileSize) { this.fileSize = fileSize; } } }
JAX-RS のプロバイダ例
- SmbFile を JAX-RS のレスポンスとして返すためのプロバイダ
package info.typea.provider; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import javax.ws.rs.Consumes; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; import jcifs.smb.SmbException; import jcifs.smb.SmbFile; import jcifs.smb.SmbFileInputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Windows ファイル共有 サービス(CIFS) ファイル 用 JAX-RS プロバイダー * * @see org.apache.wink.common.internal.providers.entity.FileProvider */ @Provider @Produces({ "*/*" }) @Consumes({ "*/*" }) public class SmbFileProvider implements MessageBodyWriter<SmbFile> { private static final Logger logger = LoggerFactory.getLogger(SmbFileProvider.class); @Override public long getSize(SmbFile t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { try { return t.length(); } catch (SmbException e) { return 0; } } @Override public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { return SmbFile.class.isAssignableFrom(type); } @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public void writeTo( SmbFile t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { try { final SmbFile smbFile = t; final OutputStream os = entityStream; AccessController.doPrivileged(new PrivilegedExceptionAction() { public Object run() throws IOException { if ((!(smbFile.canRead())) || (smbFile.isDirectory())) { if (SmbFileProvider.logger.isWarnEnabled()) { SmbFileProvider.logger.error(String .format("cannotUseFileAsResponse %s", smbFile.getPath())); } throw new WebApplicationException(); } SmbFileInputStream fis = new SmbFileInputStream(smbFile); try { SmbFileProvider.this.pipe(fis, os); } finally { fis.close(); } return null; } }); } catch (PrivilegedActionException e) { if (e.getException() instanceof IOException) throw ((IOException) e.getException()); if (e.getException() instanceof WebApplicationException) throw ((WebApplicationException) e.getException()); throw new WebApplicationException(e.getException()); } } private void pipe(InputStream is, OutputStream os) throws IOException { byte[] ba = new byte[1024]; int i = is.read(ba); while (i != -1) { os.write(ba, 0, i); i = is.read(ba); } } }
© 2006 矢木浩人