Java SMB Integration: Configuration, URL Formats, and File Operations with JCIFS
SMB overview
Server Message Block (SMB) is a network protocol for sharing files, printers, and other resources over a LAN. Windows ships with both client and server implementations. On Unix-like systems, Samba provides a compatible SMB server/client stack. CIFS is an earlier dialect of SMB commonly exposed on the internet.
Enabling SMB on Windows
- Open Control Panel → Programs → Turn Windows features on or off
- Enable "SMB 1.0/CIFS File Sharing Support" and check the components you require (e.g., SMB 1.0/CIFS Client and Server)
Verify protocol switches with PowerShell:
- Get-SmbServerConfiguration | Select EnableSMB1Protocol, EnableSMB2Protocol, EnableSMB3Protocol
Create a shared folder:
- Create a folder, open Properties → Sharing → Advanced Sharing, enable sharing, and configure permissions for the desired users
- Access via UNC in Explorer or a shell: \HOSTNAME\ShareName
Maven dependency
Add JCIFS to your project:
<!-- JCIFS (classic) -->
<dependency>
<groupId>jcifs</groupId>
<artifactId>jcifs</artifactId>
<version>1.3.17</version>
</dependency>
SMB URL patterns in Java
Typical jcifs.smb.SmbFile URLs:
- Anonymous share: smb:///
- Example: smb://192.168.1.20/public
- Basic credentials embedded: smb://:@/
- Example: smb://alice:Secr3t!@10.0.0.15/docs
- Domain credentials: smb://;:@//path/to/file.ext
- Example: smb://ACME;svc-build:Passw0rd@172.16.0.5/builds/app.zip
When credentials contain special characters, prefer programmatic authentication rather than embedding them in the URL.
File operations against SMB shares
The examples below demonstrate download, upload, and existence checks using JCIFS. The operations work by constructing SmbFile instances and reading/writing streams.
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileInputStream;
import jcifs.smb.SmbFileOutputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class SmbIoDemo {
private static final String SMB_BASE = "smb://username:password@192.168.1.103/Test"; // no trailing slash
private static final String REMOTE_SUBDIR = "SmbTest/GoalTest"; // forward slashes for URLs
private static final String SAMPLE_FILE = "test.txt";
private static final String LOCAL_DIR = "D:/LocalTest";
public static void main(String[] args) {
fetchFromShare(SMB_BASE, REMOTE_SUBDIR, SAMPLE_FILE, LOCAL_DIR);
pushToShare(SMB_BASE, REMOTE_SUBDIR, SAMPLE_FILE, LOCAL_DIR);
}
// Download a file from SMB to a local folder
public static void fetchFromShare(String smbRoot, String remotePath, String fileName, String localFolder) {
String remoteUrl = joinUrl(smbRoot, remotePath, fileName);
File dest = new File(localFolder, fileName);
try (InputStream in = new BufferedInputStream(new SmbFileInputStream(new SmbFile(remoteUrl)));
OutputStream out = new BufferedOutputStream(new FileOutputStream(dest))) {
transfer(in, out);
} catch (IOException e) {
e.printStackTrace();
}
}
// Upload a local file into an SMB share
public static void pushToShare(String smbRoot, String remotePath, String fileName, String localFolder) {
String remoteUrl = joinUrl(smbRoot, remotePath, fileName);
File src = new File(localFolder, fileName);
try (InputStream in = new BufferedInputStream(new FileInputStream(src));
OutputStream out = new BufferedOutputStream(new SmbFileOutputStream(new SmbFile(remoteUrl)))) {
transfer(in, out);
} catch (IOException e) {
e.printStackTrace();
}
}
// Copy bytes from input to output
private static void transfer(InputStream in, OutputStream out) throws IOException {
byte[] buf = new byte[8192];
int n;
while ((n = in.read(buf)) != -1) {
out.write(buf, 0, n);
}
out.flush();
}
// Compose an SMB URL with forward slashes
private static String joinUrl(String root, String subPath, String file) {
String r = trimEndSlash(root);
String p = trimSlashes(subPath);
return r + "/" + p + "/" + file;
}
private static String trimEndSlash(String s) {
if (s.endsWith("/")) return s.substring(0, s.length() - 1);
return s;
}
private static String trimSlashes(String s) {
int start = 0, end = s.length();
while (start < end && (s.charAt(start) == '/' || s.charAt(start) == '\\')) start++;
while (end > start && (s.charAt(end - 1) == '/' || s.charAt(end - 1) == '\\')) end--;
return s.substring(start, end).replace('\\', '/');
}
}
Checking whether a remote file exists
import jcifs.smb.SmbFile;
public class SmbExistence {
public static boolean exists(String smbRoot, String remotePath, String fileName) {
String url = joinUrl(smbRoot, remotePath, fileName);
try {
SmbFile f = new SmbFile(url);
return f.exists();
} catch (Exception e) {
return false;
}
}
private static String joinUrl(String root, String subPath, String file) {
String r = root.endsWith("/") ? root.substring(0, root.length() - 1) : root;
String p = subPath.replace('\\', '/');
if (p.startsWith("/")) p = p.substring(1);
if (p.endsWith("/")) p = p.substring(0, p.length() - 1);
return r + "/" + p + "/" + file;
}
}
Authentication and handling special characters
Embedding credentials in an SMB URL can break when usernames or passwords contain characters like @, :, or /. Instead, authenticate explicit with NtlmPasswordAuthentication and pass it to SmbFile.
import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbFile;
public class SmbAuthExample {
public static void main(String[] args) throws Exception {
String server = "192.168.170.13";
String shareRoot = "smb://" + server + "/share"; // e.g., smb://192.168.170.13/share
String folderPath = "reports/2026";
String domain = "ORCL"; // or hostname
String user = "user.name";
String pass = "Str0ng:P@ss/with#chars";
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(domain, user, pass);
SmbFile dir = new SmbFile(shareRoot + "/" + folderPath + "/", auth);
if (!dir.exists()) {
dir.mkdirs();
}
SmbFile remoteFile = new SmbFile(dir, "monthly.pdf");
// Use SmbFileOutputStream/SmbFileInputStream with the 'remoteFile' as shown earlier
}
}
Notes:
- When using domain accounts, pass the domain separate via NtlmPasswordAuthentication instead of placing it in the URL.
- If you must embed credentials into the URL, percent-encode special characters, but programmatic authentication is recommended to avoid encoding pitfalls.
- Ensure the Windows share permissions and NTFS ACLs both grant the required access to the account you use.