diff --git a/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java b/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java
index 3c3e1ef910d9fb77d8b29282f15ffe5ca8498a61..09e397c7a2f802b7bd780591de8e06de8e261674 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java
@@ -1037,21 +1037,26 @@ public boolean canRead() {
 	 * @throws org.sleuthkit.datamodel.TskCoreException If the local path is not
 	 *                                                  set.
 	 */
-	private void loadLocalFile() throws TskCoreException {
-		if (!localPathSet) {
-			throw new TskCoreException(
-					BUNDLE.getString("AbstractFile.readLocal.exception.msg1.text"));
-		}
-
+	private synchronized void loadLocalFile() throws TskCoreException {
+		
 		// already been set
 		if (localFile != null) {
 			return;
 		}
+		
+		if (location.equals(TskData.FileLocation.LOCAL)) {
+			if (!localPathSet) {
+				throw new TskCoreException(
+						BUNDLE.getString("AbstractFile.readLocal.exception.msg1.text"));
+			}
 
-		synchronized (this) {
 			if (localFile == null) {
 				localFile = new java.io.File(localAbsPath);
 			}
+		} else {
+			// Copy the file from the server
+			localFile = getSleuthkitCase().loadFromFileService(this);
+			
 		}
 	}
 
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
index 057312d91e6ab46512522088c19b15c0958eb308..d8923b96da59ae55393556f65b1559b153b9c220 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
@@ -6984,75 +6984,6 @@ public LocalFile addLocalFile(String fileName, String localPath,
 				isFile, encodingType,
 				parent, transaction);
 	}
-	
-	/**
-	 * TODO
-	 * Adds a local/logical file to the case database. The database operations
-	 * are done within a caller-managed transaction; the caller is responsible
-	 * for committing or rolling back the transaction.
-	 *
-	 * @param fileName     The name of the file.
-	 * @param localPath    The absolute path (including the file name) of the
-	 *                     local/logical in secondary storage.
-	 * @param size         The size of the file in bytes.
-	 * @param ctime        The changed time of the file.
-	 * @param crtime       The creation time of the file.
-	 * @param atime        The accessed time of the file
-	 * @param mtime        The modified time of the file.
-	 * @param md5          The MD5 hash of the file.
-	 * @param sha256       The SHA256 hash of the file.
-	 * @param known        The known status of the file (can be null)
-	 * @param mimeType     The MIME type of the file
-	 * @param isFile       True, unless the file is a directory.
-	 * @param encodingType Type of encoding used on the file
-	 * @param parent       The parent of the file (e.g., a virtual directory)
-	 * @param transaction  A caller-managed transaction within which the add
-	 *                     file operations are performed.
-	 *
-	 * @return An object representing the local/logical file.
-	 *
-	 * @throws TskCoreException if there is an error completing a case database
-	 *                          operation.
-	 */
-	public LocalFile addRemoteLocalFile(String fileName, String localPath,
-			long size, long ctime, long crtime, long atime, long mtime,
-			String md5, String sha256, FileKnown known, String mimeType,
-			boolean isFile, TskData.EncodingType encodingType,
-			Content parent, CaseDbTransaction transaction) throws TskCoreException {	
-		
-		File file = new File(localPath);
-		
-		// curl -X POST "http://localhost:8080/api/files" -H "accept: application/json" -H "Content-Type: multipart/form-data" -F "file=@Report.xml"
-		List<String> command = new ArrayList<>();
-		command.add("curl");
-		command.add("-X");
-		command.add("POST");
-		command.add("http://localhost:8080/api/files");
-		command.add("-H");
-		command.add("accept: application/json");
-		command.add("-H");
-		command.add("Content-Type: multipart/form-data");
-		command.add("-F");
-		command.add("file=@" + file.getAbsolutePath());
-		
-		System.out.println("### Process builder commands");
-		for(String s:command){
-			System.out.println("  " + s);
-		}
-		
-		ProcessBuilder processBuilder = new ProcessBuilder(command).inheritIO();
-		try {
-			Process process = processBuilder.start();
-		} catch (IOException ex) {
-			ex.printStackTrace();
-		}
-		
-		return addLocalFile(fileName, localPath,
-				size, ctime, crtime, atime, mtime,
-				md5, sha256, known, mimeType,
-				isFile, encodingType,
-				parent, TskData.FileLocation.MICROSERVICE, transaction);
-	}
 
 	/**
 	 * Adds a local/logical file to the case database. The database operations
@@ -7500,6 +7431,132 @@ private void updateFilePath(CaseDbConnection connection, long objId, String path
 		statement.setLong(3, objId);
 		connection.executeUpdate(statement);
 	}
+	
+	// TEMP TEMP
+	// Should be set at the same time as the file service server
+	File getFileServiceTempFolder() {
+		return new File("R:\\mytemp");
+	}
+	
+	File loadFromFileService(AbstractFile abstractFile) throws TskCoreException {
+		if (! abstractFile.getFileLocation().equals(TskData.FileLocation.MICROSERVICE)) {
+			throw new TskCoreException("Not file service");
+		}
+		
+		// TODO verify there's a hash (there should be)
+		
+		// TODO check existence first?
+		String downloadPath = Paths.get(getFileServiceTempFolder().toString(), abstractFile.getSha256Hash()).toString();
+		downloadFileFromFileService(abstractFile, downloadPath);
+		
+		File tempFile = new File(downloadPath);
+		if (tempFile.exists()) {
+			// YAY!
+			return tempFile;
+		} else {
+			System.out.println("\n### oh no... " + tempFile.toString() + " does not exist");
+			throw new TskCoreException("error");
+		}
+		
+	}
+	
+	private void downloadFileFromFileService(AbstractFile file, String downloadPath) {
+		
+		// curl -X GET "http://localhost:8080/api/files/(hash value)" -H "accept: */*" --output downloadPath
+		List<String> command = new ArrayList<>();
+		command.add("curl");
+		command.add("-X");
+		command.add("GET");
+		command.add("http://localhost:8080/v1/files/" + file.getSha256Hash());
+		command.add("-H");
+		command.add("accept: */*");
+		command.add("--output");
+		command.add(downloadPath);
+		
+		System.out.println("### Process builder commands");
+		for(String s:command){
+			System.out.println("  " + s);
+		}
+		
+		ProcessBuilder processBuilder = new ProcessBuilder(command).inheritIO();
+		try {
+			Process process = processBuilder.start();
+			process.waitFor();
+		} catch (IOException | InterruptedException ex) {
+			ex.printStackTrace();
+		}	
+		
+		
+	}
+	
+	/**
+	 * TODO: should be abstractFile or content?
+	 * @param abstractFile 
+	 */
+	public void saveToFileService(AbstractFile abstractFile, CaseDbTransaction trans) throws TskCoreException {
+		
+		if (abstractFile.getLocalPath() == null || abstractFile.getLocalPath().isEmpty()) {
+			// TODO
+			System.out.println("Not supported yet\n");
+		} else {
+			// Make sure the SHA-256 hash has been calculated
+			if (abstractFile.getSha256Hash() == null || abstractFile.getSha256Hash().isEmpty()) {
+				HashUtility.calculateHashes(abstractFile, Arrays.asList(HashUtility.HashType.SHA256));
+				abstractFile.save();
+			}
+			
+			// Save the abstractFile data
+			saveLocalFileToFileService(abstractFile);
+			
+			// Update the file table entry
+			try {
+				CaseDbConnection connection = trans.getConnection();
+				PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_FILE_SERVICE_FILE);
+				statement.clearParameters();
+				
+				statement.setLong(1, TskData.FileLocation.MICROSERVICE.getValue());
+				statement.setLong(2, abstractFile.getId());
+				
+				connection.executeUpdate(statement);
+				
+				// TODO remove local path
+				
+			} catch (SQLException ex) {
+				ex.printStackTrace();
+			}
+		}
+		
+	}
+	
+	private void saveLocalFileToFileService(AbstractFile abstractFile) {
+		File file = new File(abstractFile.getLocalPath());
+		
+		// curl -X POST "http://localhost:8080/api/files" -H "accept: application/json" -H "Content-Type: multipart/form-data" -F "file=@Report.xml"
+		List<String> command = new ArrayList<>();
+		command.add("curl");
+		command.add("-X");
+		command.add("POST");
+		command.add("http://localhost:8080/v1/files");
+		command.add("-H");
+		command.add("accept: application/json");
+		command.add("-H");
+		command.add("Content-Type: multipart/form-data");
+		command.add("-F");
+		command.add("file=@" + file.getAbsolutePath());
+		
+		System.out.println("### Process builder commands");
+		for(String s:command){
+			System.out.println("  " + s);
+		}
+		
+		ProcessBuilder processBuilder = new ProcessBuilder(command).inheritIO();
+		try {
+			Process process = processBuilder.start();
+			process.waitFor();
+		} catch (IOException | InterruptedException ex) {
+			ex.printStackTrace();
+		}	
+	}
 
 	/**
 	 * Find all files in the data source, by name and parent
@@ -11460,7 +11517,8 @@ private enum PREPARED_STATEMENT {
 		INSERT_FS_INFO("INSERT INTO tsk_fs_info (obj_id, data_source_obj_id, img_offset, fs_type, block_size, block_count, root_inum, first_inum, last_inum, display_name)"
 				+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"),
 		SELECT_TAG_NAME_BY_ID("SELECT * FROM tag_names where tag_name_id = ?"),
-		SELECT_TAG_NAME_BY_NAME("SELECT * FROM tag_names where display_name = ?");
+		SELECT_TAG_NAME_BY_NAME("SELECT * FROM tag_names where display_name = ?"),
+		UPDATE_FILE_SERVICE_FILE("UPDATE tsk_files SET location = ? WHERE obj_id = ?");
 
 		private final String sql;