| ページ一覧 | ブログ | twitter |  書式 | 書式(表) |

MyMemoWiki

「Java Windowsファイル共有サービス(CIFS)経由でファイルを書き込む」の版間の差分

提供: MyMemoWiki
ナビゲーションに移動 検索に移動
 
13行目: 13行目:
 
  import java.io.FileOutputStream;
 
  import java.io.FileOutputStream;
 
  import java.io.InputStream;
 
  import java.io.InputStream;
  import java.net.MalformedURLException;
+
  import java.net.MalformedU[[R]]LException;
 
   
 
   
 
  import jcifs.smb.SmbException;
 
  import jcifs.smb.SmbException;
33行目: 33行目:
 
      
 
      
 
     /**
 
     /**
       * 通常のファイルシステムもしくは CIFS(Windowsファイル共有サービス) にファイルを書き込む
+
       * 通常のファイルシステムもしくは CIFS([[Windows]]ファイル共有サービス) にファイルを書き込む
 
       *  
 
       *  
 
       * @param is 書き込み内容
 
       * @param is 書き込み内容
75行目: 75行目:
 
                     cisfPath(targetFile.getAbsolutePath())));
 
                     cisfPath(targetFile.getAbsolutePath())));
 
              
 
              
         } catch (MalformedURLException e) {
+
         } catch (MalformedU[[R]]LException e) {
 
             // TODO
 
             // TODO
 
         }
 
         }
171行目: 171行目:
 
       * @param user
 
       * @param user
 
       * @param password
 
       * @param password
       * @throws MalformedURLException
+
       * @throws MalformedU[[R]]LException
 
       * @throws SmbException
 
       * @throws SmbException
 
       */
 
       */
177行目: 177行目:
 
             File dir,  
 
             File dir,  
 
             String user,  
 
             String user,  
             String password) throws MalformedURLException, SmbException {
+
             String password) throws MalformedU[[R]]LException, SmbException {
 
          
 
          
 
         SmbFile cifsDir = new SmbFile(
 
         SmbFile cifsDir = new SmbFile(
191行目: 191行目:
 
      
 
      
 
     /**
 
     /**
       * CIFS アクセス URL
+
       * CIFS アクセス U[[R]]L
 
       * @param user
 
       * @param user
 
       * @param password
 
       * @param password
201行目: 201行目:
 
     }
 
     }
 
     /**
 
     /**
       * '@' is URL encoded with the '%40' hexcode escape
+
       * '@' 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.provider;
+
  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.AccessController;
+
  import java.security.[[Access]]Controller;
  import java.security.PrivilegedActionException;
+
  import java.security.Pri[[vi]]legedActionException;
  import java.security.PrivilegedExceptionAction;
+
  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.Provider;
+
  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.providers.entity.FileProvider
+
   * @see org.apache.wink.common.internal.pro[[vi]]ders.entity.FilePro[[vi]]der
 
   */
 
   */
  @Provider
+
  @Pro[[vi]]der
 
  @Produces({ "*/*" })
 
  @Produces({ "*/*" })
 
  @Consumes({ "*/*" })
 
  @Consumes({ "*/*" })
  public class SmbFileProvider implements MessageBodyWriter<SmbFile> {
+
  public class SmbFilePro[[vi]]der implements MessageBodyWriter<SmbFile> {
     private static final Logger logger = LoggerFactory.getLogger(SmbFileProvider.class);
+
     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> httpHeaders,
+
             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;
 
              
 
              
             AccessController.doPrivileged(new PrivilegedExceptionAction() {
+
             [[Access]]Controller.doPrivileged(new PrivilegedExceptionAction() {
 
                 public Object run() throws IOException {
 
                 public Object run() throws IOException {
                     if ((!(smbFile.canRead())) || (smbFile.isDirectory())) {
+
                     if ((!(smbFile.can[[R]]ead())) || (smbFile.isDirectory())) {
                         if (SmbFileProvider.logger.isWarnEnabled()) {
+
                         if (SmbFilePro[[vi]]der.logger.isWarnEnabled()) {
                             SmbFileProvider.logger.error(String
+
                             SmbFilePro[[vi]]der.logger.error(String
                                 .format("cannotUseFileAsResponse %s", smbFile.getPath()));
+
                                 .format("cannotUseFileAs[[R]]esponse %s", smbFile.getPath()));
 
                         }
 
                         }
 
   
 
   
323行目: 323行目:
 
                     SmbFileInputStream fis = new SmbFileInputStream(smbFile);
 
                     SmbFileInputStream fis = new SmbFileInputStream(smbFile);
 
                     try {
 
                     try {
                         SmbFileProvider.this.pipe(fis, os);
+
                         SmbFilePro[[vi]]der.this.pipe(fis, os);
 
                     } finally {
 
                     } finally {
 
                         fis.close();
 
                         fis.close();
331行目: 331行目:
 
                 }
 
                 }
 
             });
 
             });
         } catch (PrivilegedActionException e) {
+
         } 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)経由でファイルを書き込む

Java | JAX-RS |

  • アプリケーションサーバー等、サービスで動くアプリケーションは、ログインユーザーとは別権限で動作しており、ファイル共有されたドライブのファイル参照、書き出しが出来ない。
  • 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);
        }
    }
}